1. ホーム
  2. git

[解決済み] GITとCVSの違い

2022-06-27 18:12:15

質問

バージョン管理システムのGitとCVSの違いは何ですか?

私は10年以上CVSを喜んで使ってきましたが、今ではGitの方がずっと良いと言われています。 この二つの違いは何なのか、なぜ一方が他方より優れているのか、どなたか説明していただけないでしょうか。

どのように解決するのですか?

主な違いは、(他の回答ですでに言われているように)CVSは(古い)集中型バージョン管理システムであり、Gitは分散型であるということです。

しかし、たとえ一人の開発者のために、一台のマシン(一人のアカウント)でバージョン管理を使うとしても、Git と CVS の間にはいくつかの相違点があります。

  • リポジトリの設定 . Gitはリポジトリを .git ディレクトリにリポジトリを保存します。CVS では、異なるプロジェクト (モジュール) のバージョン管理情報を保存する中央の場所である CVSROOT を設定する必要があります。その結果、既存のソースをバージョン管理に取り込むのは、Git では "git init &&git add ... &git commit" のように簡単なのに対して、ユーザーにとっては より複雑です。 であるのに対して、CVSではもっと複雑です。

  • アトミック操作 . CVS は当初、ファイルごとの RCS バージョン管理システム周りのスクリプトのセットだったので、コミット (と他の操作) は CVS ではアトミックではありません。リポジトリに対する操作が途中で中断されると、リポジトリは矛盾した状態で残される可能性があります。Gitでは、すべての操作はアトミックです。全体として成功するか、何も変更されずに失敗するかのどちらかです。

  • チェンジセット . CVS での変更はファイル単位ですが、Git での変更 (コミット) は常にプロジェクト全体を参照します。これは非常に重要なことです。 パラダイムシフト . この結果、Git では簡単に元に戻す (元に戻す変更を作成する) ことができるようになりました。 全体 もう一つの結果は、CVSでは部分的なチェックアウトが簡単にできるのに対し、Gitではそれがほとんど不可能であるということです。変更はファイルごとにあり、グループ化されているという事実が、CVSでのコミットメッセージのためのGNU Changelogフォーマットの発明へとつながりました。Gitユーザーは、変更を説明する(要約する)一行、空行、変更の詳細な説明の続く、異なる慣習を使っており(いくつかのGitツールはそれを期待しています)、その結果、CVSは、変更されたファイルについて、より詳細に説明することが可能になりました。

  • リビジョン/バージョン番号の命名 . CVS では変更がファイル単位であることに関連した別の問題があります: バージョン番号 (時々 キーワード展開 1.4 のようなバージョン番号は、与えられたファイルが何回変更されたかを反映します。Git では、プロジェクト全体(各コミット)の各バージョンは SHA-1 ID で与えられるユニークな名前を持っており、通常最初の 7-8 文字でコミットを識別できます(分散バージョン管理システムでは、バージョンに対して単純な番号付けはできません -- 中央の番号付け機関が必要です)。CVS では、プロジェクト全体の状態を示すバージョン番号やシンボリック名を付けるには、次のようにします。 タグを使います。 Gitでも、プロジェクトのあるバージョンに「v1.5.6-rc2」のような名前を使いたい場合は同じことが言えますが... Gitのタグはずっと使いやすいのです。

  • 簡単な分岐 . CVS のブランチは、私の意見では、過度に複雑で、扱いにくいものです。リポジトリ全体のブランチの名前を持つためにブランチにタグを付けなければなりません (そして、私の記憶が正しければ、ファイルごとの処理のために、それさえもいくつかのケースで失敗することがあります)。それに加えて、CVS には マージ追跡 がないため、マージとブランチポイントを覚えておくか、手動でタグ付けし、ブランチをマージするために "cvs update -j" に正しい情報を手動で与えなければならないという事実が加わり、ブランチを使うのが不必要に難しくなっています。Gitでは、ブランチの作成とマージはとても簡単です。Gitは必要な情報をすべて自分で記憶しています(そのため、ブランチのマージは "git merge ブランチ名 というのも、分散開発では当然複数のブランチが必要になるからです。

    これはつまり トピックブランチ を使うことができるようになったということです。

  • トラッキングのリネーム(およびコピー) . ファイルのリネームは CVS ではサポートされておらず、手動でのリネームは履歴を二つに分けたり、リネーム前のプロジェクトの状態を正しく回復できない無効な履歴につながる可能性があります。Git では、コンテンツとファイル名の類似性に基づいて、ヒューリスティックにリネームを検出します (このソリューションは、実際にうまく機能します)。また、ファイルのコピーの検出を要求することもできます。これは、次のことを意味します。

    • 指定されたコミットを調査する際に、あるファイルの名前が変更されたという情報を得ることができます。
    • マージはリネームを正しく考慮します(例えば、ファイル名が変更されたのが一つのブランチのみであった場合)。
    • ファイル内容の行単位の履歴を表示するツールである "cvs annotate" の(より良い)同等品である "git blame" は、リネームをまたいでコードの動きを追うことができます。
  • バイナリファイル . CVS はバイナリファイル (例えば画像) を非常に限定的にしかサポートしておらず、バイナリファイルを行末変換やキーワード展開でマングリングしないように、追加時に明示的に (あるいは後で "cvs admin" や、ファイル名から自動的に行うラッパーを使って) マークすることが要求されます。Gitは、CNU diffや他のツールと同じように、内容に基づいてバイナリファイルを自動的に検出します。この検出は、gitattributesメカニズムを使ってオーバーライドできます。さらに、バイナリファイルは、デフォルトの 'safecrlf' のおかげで回復不能なマングリングに対して安全であり、(ディストリビューションによってはデフォルトでオンになっているかもしれませんが)行末変換を要求しなければならないという事実や、(制限付き)キーワード展開が Git で厳密に 'opt-in' となっているという事実があります。

  • キーワード展開 . Gitは、CVSと比較して(デフォルトでは)非常に、非常に限られたキーワードのセットを提供します。これは、2つの事実のためです。Gitでの変更は、ファイルごとではなく、リポジトリごとに行われ、Gitは、他のブランチに切り替えたり、歴史の他の時点に巻き戻したりするときに、変更していないファイルを修正することを避けています。もしあなたがGitを使ってリビジョン番号を埋め込みたいなら、あなたのビルドシステムを使ってこれを行うべきです。例えば、次の例はLinuxカーネルソースとGitソースにあるGIT-VERSION-GENスクリプトです。

  • コミットの修正 . なぜなら、Gitのような分散型VCSにおいて を発行する はコミットを作成することとは別なので、他のユーザーに迷惑をかけることなく、未公開の履歴を変更(編集、書き換え)することができます。特に、コミットメッセージのタイプミス(またはその他のエラー)やコミットのバグに気づいた場合は、単に "git commit --amend" を使用することができます。これは CVS では不可能です (少なくとも重いハックなしでは)。

  • その他のツール . Git は CVS よりもはるかに多くのツールを提供しています。より重要なものの一つが " です。 git bisect これは、バグを導入したコミット(リビジョン)を見つけるために使うことができます。もしあなたのコミットが小さく、自己完結していれば、バグの場所を見つけるのはかなり簡単なはずです。


もしあなたが少なくとも一人の他の開発者と共同作業をしているのであれば、Git と CVS の間に以下のような違いも見出すでしょう。

  • マージ前のコミット Git は コミットビフォアマージ ではなく、CVSのように マージビフォアコミット (あるいは 更新後コミット ). もし、あなたがファイルを編集していて、新しいコミット(新しいリビジョン)を作成する準備をしている間に、他の誰かが同じブランチで新しいコミットを作成し、それが現在リポジトリにある場合、CVSはあなたにコミットを許可する前に、まず作業ディレクトリを更新して競合を解決することを強制します。これは、Git の場合ではありません。まずコミットして自分の状態をバージョン管理内に保存し、それから他の開発者の変更をマージします。他の開発者にマージとコンフリクトの解消を依頼することもできます。

    もし、履歴を線形にし、マージを避けたいのであれば、いつでも コミット・マージ・再コミット ワークフローは "git rebase" (および "git pull --rebase") を通して行われ、更新された状態の上で変更を再生するという点では CVS と同様です。しかし、常に最初にコミットする必要があります。

  • セントラルリポジトリが不要 Git では、変更をコミットするための単一の中心的な場所を持つ必要はありません。各開発者は自分のリポジトリ(あるいは、より良いリポジトリ:彼/彼女が開発を行うプライベートなものと、準備ができた部分を公開する公開されたもの)を持つことができ、彼らは対称的な方法で、互いのリポジトリから取得/取得することができます。一方、大規模なプロジェクトでは一般的に 社会的に 定義/指名された中央リポジトリがあり、そこから全員がプルする(変更を取得する)のが一般的です。


最後に、多くの開発者との共同作業が必要な場合、Git はより多くの可能性を提供します。以下では、プロジェクトにおける関心と立場の異なる段階(CVS または Git を使用したバージョン管理下)での CVS と Git の違いを説明します。

  • ラーカー . もしあなたがプロジェクトの最新の変更点を取得することだけに興味があるのなら、( あなたの変更を伝搬させない )、あるいは プライベート 開発をしている (元のプロジェクトに貢献しない)、または海外のプロジェクトを自分のプロジェクトの基盤として使用している (変更はローカルであり、それを公開することに意味はない)、などです。

    Git はここをサポートしています。 匿名・未認証 効率的なカスタムによる読み取り専用アクセス git:// プロトコルを使用するか、またはファイアウォールで DEFAULT_GIT_PORT (9418)をブロックするファイアウォールがある場合は、プレーンなHTTPを使用することができます。

    CVS の場合、読み取り専用アクセスのための最も一般的な解決策は (私が理解する限り) ゲストアカウント で 'pserver' プロトコルの CVS_AUTH_PORT (2401) で、通常は "anonymous" と呼ばれ、パスワードは空です。認証情報はデフォルトで $HOME/.cvspass ファイルに保存されますので、一度だけそれを提供する必要があります。 それでも、これはちょっとした障壁 (ゲストアカウントの名前を知っているか、 CVS サーバのメッセージに注意を払う必要があります) であり、厄介なものです。

  • フリンジデベロッパー(リーフコントリビューター) . OSSで自分の変更を伝播させる方法の1つは 電子メールでパッチを送る . これは、あなたが(多かれ少なかれ)偶然の開発者であり、単一の変更、または単一のバグフィックスを送信する場合、最も一般的なソリューションです。ちなみに、パッチの送信はメールだけでなく、レビューボード (パッチレビューシステム) や同様の手段を使うこともあります。

    Git は、送信者 (クライアント) と保守者 (サーバー) の両方に対して、この伝播 (公開) のメカニズムを支援するツールを提供します。電子メールで変更を送信したい人のために、" があります。 git rebase (または "git pull --rebase") は、自分の変更を現在の上流バージョンの上で再生するツールで、自分の変更が現在のバージョンの上にある (新鮮である) ようにします。 git format-patch コミットメッセージ(と作者名)、(拡張)統一差分フォーマット(とレビューを容易にする diffstat)の形式での変更を含むメールを作成する "。管理者はこのようなメールを、(コミットメッセージを含む)すべての情報を保持したまま直接コミットにすることができます(" git am とします。

    CVS にはそのようなツールはありません。変更を生成するために "cvs diff" / "cvs rdiff" を使用し、変更を適用するために GNU patch を使用できますが、私の知る限り、コミットメッセージを自動的に適用する方法はありません。CVS は、クライアント <-> サーバ方式で使用されることを意図しています....

  • 中尉 . もしあなたがプロジェクトの個別の部分 (サブシステム) のメンテナなら、あるいはあなたのプロジェクトの開発が Linux カーネルの開発で使われた "network of trust" ワークフローに従っているなら、あるいは単にあなた自身の公開リポジトリを持っていて、公開したい変更がメールで送るには大きすぎて パッチ シリーズ としてメールで送るには大きすぎる場合、次のように送ることができます。 プルリクエスト をプロジェクトの(main)メンテナに送ってください。

    これは 分散型 バージョン管理システム特有のソリューションです。git request-pull" というツールもあり、リポジトリからのプルリクエストをメンテナに送るためのメールを準備することができます。git bundle" のおかげで、公開リポジトリを持っていなくても、メールやスニーカーネット経由で変更のバンドルを送信することで、この仕組みを利用することができます。Git ホスティングサイトには、次のようなものがあります。 GitHub のような Git ホスティングサイトには、誰かがあなたのプロジェクトで作業している (何らかの作業を公開した) ことを通知したり (その人が同じ Git ホスティングサイトを使っている場合)、一種のプルリクエストを PM したりするためのサポートがあります。

  • メイン開発者 つまり 直接公開する する人です。このカテゴリは分散型バージョン管理システムでより広い範囲に及びます。 を押す の変更を正規のリポジトリに移し、lieutenants/subsystem maintainers のセットからパッチを取得し、広範なリーフ開発者が maintainer/project mailing list や lieutenants/submaintainers のいずれかにメールでパッチを送ります) 。

    Git では SSH プロトコル (git protocol wrapped in SSH) を使って変更を公開し、"git shell" (シェルアカウントのアクセスを制限してセキュリティを向上させる) などのツールを使うか、あるいは Gitosis (別のシェルアカウントを必要とせずにアクセスを管理する)、および HTTPS で、通常の HTTP 認証で WebDAV を使用します。

    CVS では、カスタム 非暗号化 (プレーン テキスト) pserver プロトコルを使用するか、あるいは リモートシェル (を使うか(本当は SSH ) を使って変更を公開することができます。 中央集権的 バージョン管理システムでは、変更をコミットする (コミットを作成する) ことを意味します。SSH を使って 'pserver' プロトコルをトンネルすることもできますし、これを自動化する第三者ツールもありますが... Gitosis などのように簡単だとは思えません。

一般的に、Gitのような分散型バージョン管理システムは、可能なワークフローのより広い選択を提供します。CVS のような集中型バージョン管理システムでは、必然的に、リポジトリへのコミット アクセスを持つ人と持たない人を区別する必要があります... そして CVS は、コミット アクセスを持たない人からの(パッチによる)貢献を受け入れることを支援するどんなツールも提供しません。

Karl Fogel (英語) オープン ソース ソフトウェアの作成 の中で、バージョン管理に関するセクションで、公開リポジトリに変更を加えることが許される領域について、あまり厳密で厳格なコントロールを提供しない方が良いと述べています。技術的な制限よりも社会的な制限(コードレビューなど)に頼る方が(これについては)ずっと良いのですが、分散バージョン管理システムはIMHOではそれをさらに軽減しています...

HTH (お役に立てれば幸いです)