SVNとGitのブランチの違いを理解する


44

私はSVNのユーザーであり、現在Gitを学んでいます。

SVNでは、通常、ローカルマシンでレポジトリをチェックアウトします。レポジトリには、プロジェクトのすべてのブランチが含まれており、興味のあるブランチのフォルダーを選択してそこで作業していました。

Gitを使用すると違いがわかります。

現在、私はリポジトリをクローンし、gitkを使用して特定のブランチをクローンしています。

プロジェクトフォルダーにはそのブランチのコンテンツのみが含まれており、SVNのようにすべてのブランチを表示することはできません。

Gitを使用してローカルリポジトリ内のすべてのブランチを表示する簡単な方法が見つかりません。

  • 私が説明したGitプロセスが「標準」であるかどうか、そしてある程度正確であるか、何か不足しているのかを知りたいです。

  • また、たとえば、マスターで修正プログラムを作成する必要があるが、別のブランチのコンテンツも保持する必要がある場合に備えて、2つのブランチで同時に作業する必要があるプロセスの処理方法を知りたいと思います。

  • Gitのリポジトリからクローンされたブランチを含むフォルダーを作成するための推奨される名前の規則は何myproject-branchnameですか?


8
興味深い-通常、SVNでは、作業中のトランクまたはブランチのみをチェックアウトしますが、その意味は理解しています。
ホルスコル

20
SVNでワークフローが壊れていたため、Gitにミラーリングしようとしました(Gitに部分的にしか適用できない優れたSVNワークフローでも)。最善の解決策- すべてのSVN習慣忘れて、Gitをゼロから開始する
レイジーバジャー

6
git clone以上のようなものですsvnadmin hotcopysvnrdump+ svnadmin loadそれのようであるよりsvn checkout。を使用gitするとリポジトリから断片を要求しません。リポジトリ全体をコピーしてローカルで操作し、必要に応じて変更を「ソース」リポジトリにプッシュします。GitとSubversionは、ソース管理に2つのまったく異なるモデルを使用します。
-chepner

1
ホットフィックスの問題に関しては、使用を検討してgit-flow
ください-Bakuriu

5
@LazyBadgerは、開発を促進し、価値を提供すれば、ワークフローが壊れることはありません。ブランチを使用する正しい方法はありません。
-Dietbuddha

回答:


67

私はSVNのユーザーであり、現在GITを学んでいます。

ギャングへようこそ!

SVN再教育

SVNでは、通常[...]

しばらくお待ちください。CVSとSVNおよびその他の従来の(つまり集中型)バージョン管理システムは、mercurialやGitなどの最新の(つまり分散型)バージョン管理システムと(ほぼ)同じ目的を果たしますが、Gitをゼロから学ぶよりもはるかに優れていますSVNワークフローをGitに転送しようとしています。

Joel Spolsky(Stack Exchangeの創設者の1人)によるhttp://hginit.comarchive.orgのビュー)は、Gitではなく水銀のチュートリアルですが、第0章「Subversion Re-education」はSVNから離れて切り替える人々のための便利な任意のそれはあなたが(一時的に)持っているものSVN概念を説明しますと、分散型バージョン管理システム国連(または-learn stash離れてあなたの頭の分散の周りにできるラップするGitのユーザーは言うかもしれないとして、)バージョン管理システムの概念と、それらと連携するために確立された慣用的なワークフロー。

したがって、そのゼロ番目の章を読んで、ほとんどの場合、「mercurial」という単語を「Git」に置き換えるだけで、Gitの準備が整います。

細字

(今のところこれをスキップするかもしれません。) mercurialとGitはSVNよりも互いに似ています、概念的な違いがあるため、「Subversion Re-education」のステートメントとアドバイスの一部は技術的に間違っています。 「mercurial」を「Git」に置き換える場合:

  • Mercurialは変更セットを内部的に追跡および保存しますが、GitはSubversionと同様に、リビジョン(つまりディレクトリツリーのコンテンツの状態)を内部的に追跡および保存します。ただし 、Subversion Git 以外は、関連する各ブランチと共通の祖先リビジョンの違いを確認してマージを実行するため(真の3ポイントマージ)、結果はMercurialの場合とほぼ同じです。マージははるかに簡単でエラーが少ない-SVNよりも発生しやすい。
  • リポジトリを複製することでGitでブランチを作成できますが(水銀の慣例に従って)、Gitリポジトリ内に新しいブランチを作成するのが一般的です。(これは、Gitブランチが単に(移動)リビジョンへのポインタであるのに対し、mercurialブランチはすべてのリビジョンに適用される永続的なラベルであるためです。これらの永続的なラベルは通常不要です。

SVNでは、すべてがディレクトリです(ただし、必ずしもそのように扱う必要はありません)

しかし、私はあなたを中断してきました。あなたは言っていました?

SVNでは、通常、ローカルマシンでレポジトリをチェックアウトします。レポジトリには、プロジェクトのすべてのブランチが含まれており、興味のあるブランチのフォルダーを選択してそこで作業していました。

それによって、SVNリポジトリのルートフォルダー(またはtrunk、1つ以上のブランチに対応する他のフォルダー、たとえば、従来のSVNリポジトリレイアウトでは、branchesすべての非トランクブランチを含むフォルダー)をチェックアウトした場合おそらくSVNの間違った(ish)を使用した、または少なくともトランク、ブランチ、タグがすべてリビジョン/コードベースのディレクトリと一緒に単一の(階層的)名前空間に折り畳まれているという事実を少し悪用したと思います。

いくつかのSVNブランチを並行して変更するのは魅力的かもしれませんが、それはSVNがどのように使用されることを意図しているかではないことです。(そのように機能する特定のマイナス面が何を持っているのかはわかりませんが。)

Gitでは、ディレクトリのみがディレクトリです

Gitリポジトリのすべてのクローンはそれ自体がGitリポジトリです。デフォルトでは、すべてのリビジョン、ブランチ、タグを含む、元のリポジトリの履歴の完全なコピーを取得します。しかし、Gitはすべてを保持します。Gitは、リポジトリのルートフォルダーの非表示.git/サブフォルダーにある、ファイルベースの種類のデータベースに保存します。

しかし、リポジトリフォルダーに表示される非隠しファイルは何ですか?

git cloneリポジトリの場合、Gitはいくつかのことを行います。大体:

  1. これは、作成先のフォルダを、そしてその中に、.git/「データベース」とサブフォルダ
  2. オリジンリポジトリのデータベースの参照(タグ、ブランチなど)を転送し、それらを新しいデータベースにコピーして、「リモート」参照としてマークするわずかに変更された名前を付けます。
  3. これらの参照が指すすべてのリビジョン(ファイルツリーの状態)、およびこれらのリビジョンが直接または推移的に参照するすべてのリビジョン(親と祖先)を新しいデータベースに転送し、新しいリモート参照が実際に保存されるようにします新しいリポジトリで利用可能なものをポイントします。
  4. オリジンリポジトリのデフォルトブランチに対応するリモートリビジョンを追跡するローカルブランチを作成します(通常master)。
  5. そのローカルブランチをチェックアウトします。

その最後のステップは、Gitがこのブランチが指すリビジョンを検索し、そこに格納されているファイルツリー(データベースは圧縮と重複排除の何らかの手段を使用)をリポジトリのルートフォルダーに展開することを意味します。そのルートフォルダーとそのすべてのサブフォルダー(特別な.gitサブフォルダーを除く)は、リポジトリの「作業コピー」と呼ばれます。そこで、現在チェックアウトされているリビジョン/ブランチのコンテンツを操作します。それらは通常のフォルダーとファイルです。ただし、リポジトリ自体(リビジョンおよび参照の「データベース」)と対話するには、gitコマンドを使用します。

Gitブランチを見て、Gitブランチと対話する

現在、私はリポジトリをクローンし、gitkを使用して特定のブランチをクローンしています。

gitk私が手に入れたバージョンでは、リポジトリを複製できません。リポジトリの履歴を表示し、ブランチを作成してブランチをチェックアウトすることのみできます。また、ブランチの「クローン」はありません。リポジトリのクローンのみ作成できます。

あなたが使用してレポのクローンを作成もしかしてgit clone ...使用して、その後、およびgitkチェックアウトブランチを?

プロジェクトフォルダーにはそのブランチのコンテンツのみが含まれており、SVNのようにすべてのブランチを表示することはできません。

[...]

  • 私が説明したgitプロセスが「標準」であり、いくつかの方法が正しいかどうかを知りたい[...]

はい、それはかなり標準です:

  • を使用してリポジトリを複製する git clone ...
  • 作業するブランチを確認するgit checkout ...か、次のようなグラフィカルツールを使用します。gikt

GITを使用してローカルリポジトリ内のすべてのブランチを表示する簡単な方法を見つけることができません。

  • [...]またはsmtがありません。

多分:

  • あなたはローカルブランチをリストすることができます git branch
  • でリモートブランチをリストするgit branch -rか、すべてのブランチをリストすることができますgit branch -a
  • を使用gitkして、完全な履歴(ローカルリポジトリが知っているすべてのブランチタグなど)を表示するために使用できます。

    gitk --all
    

複数のブランチを並行して使用する方法

  • また、たとえば、マスターで修正プログラムを作成する必要があるが、別のブランチのコンテンツも保持する必要がある場合に備えて、2つのブランチで同時に作業する必要があるプロセスの処理方法を知りたいと思います。

ここにはさまざまなシナリオがあります。

新しい(まだ作成されていない)変更を複数のブランチに適用する必要があります

このワークフローを使用します。

  1. cこれらのすべてのブランチの祖先に既にあるリビジョン(たとえば、変更がバグ修正となるときにバグを導入したリビジョン)または(すべての祖先を含む)に受け入れられるリビジョンから新しいブランチを作成します。これらすべてのブランチ。
  2. その新しいブランチで変更を行い、コミットしますc
  3. b変更が必要なブランチごとに:

    1. チェックアウトb

      git checkout b
      
    2. c統合b

      git merge c
      
  4. ブランチを削除c

    git branch --delete c
    

別のブランチで既存の変更が必要です

(...しかし、その変更が存在する場所で行われた他の変更なし)

  1. 変更が必要なブランチをチェックしてください
  2. 変更を行っているリビジョンを順番にチェリーピックします

1つのブランチでa、1つまたはいくつかのファイルを別のブランチの正確な状態に変更したいb

  1. チェックアウト a
  2. ブランチからファイルの内容を取得しますb

    git checkout b -- path/to/a/file.txt path/to/another/file.cpp or/even/a/complete/directory/ ...
    

    git checkoutパスを渡さないこと以外は、ブランチに切り替えb、そこから要求されたファイルの内容のみを取得します。これらのファイルは既に存在するa場合も存在しない場合もありますb

あるブランチで作業中に、別のブランチでの状況を確認したい場合

作業したいブランチをチェックしてください。

次に、他のブランチを見るために、

  • 現在チェックアウトされていないリビジョンの内容を表示できるグラフィカルツールを使用します(gitkラジオボタンを「パッチ」から「ツリー」に切り替えようとする場合など)
  • または、リポジトリを一時ディレクトリに複製して、そこにある他のブランチをチェックアウトします
  • または、同じリポジトリのgit worktree別の作業ディレクトリを作成するために使用します(つまり.git/、現在のローカルリポジトリのディレクトリ内のデータベースも使用します)

最後のワークフローでstashは、理想的です。
CAD97

@ CAD97ではなく、最初のブランチで作業を続け、2番目のブランチを並行して参照する場合git stash未完成の作業を邪魔にならないように、たとえばブランチを切り替えて後で戻るのに適しています。
DAS-G

1
「mercurialワークフローは通常、開発の分岐のために完全なリポジトリを複製することで機能します」-ええ、私はこれを聞いたことがありますが、Gitブランチを必要とするほとんどの人はリポジトリ全体を複製するのではなくブックマークを使用します。はるかに簡単です。
ケビン

@Kevinそれはそうかもしれない。しばらく前にMercurialを使用したことがあるので、当時は違うかもしれません。(または多分それは私が一緒に使用したコミュニティのワークフローだけでした。)
das-g

Hg Initのテキスト「[...]は本当にMercurialの方法で分岐しているはずなので、リポジトリを複製することにより[...]」もその点で更新する必要があります。
DAS-G

31

SVNでは、通常、ローカルマシンでレポジトリをチェックアウトします。レポジトリには、プロジェクトのすべてのブランチが含まれており、興味のあるブランチのフォルダーを選択してそこで作業していました。

トランクの上のディレクトリをチェックアウトしない限り、Subversionでは通常、すべてのブランチがローカルで利用できるわけではありません。Gitでは、すべてのコンテンツ(コミット、メッセージ、ブランチなど)は常にすべてのコピーに複製されます。

現在、私はリポジトリをクローンし、gitkを使用して特定のブランチをクローンしています。

不可能です。上記を参照してください。できますがgit checkout branch-name、できませんgit clone something branch-name。Subversionでは、ブランチはフォルダーです。Gitでは、ブランチはコミットへのポインターです。

GITを使用してローカルリポジトリ内のすべてのブランチを表示する簡単な方法を見つけることができません。

を実行しますgit branch。デフォルトでは、ローカルブランチのみが表示されます。git branch --remoteリモートブランチを見るために使用します。


4
ふむ 「デフォルトでは、ローカルブランチのみが表示されます。」ローカルではない他のタイプのブランチがあるように聞こえます。しかし、「Gitでは、すべてのコンテンツ(コミット、メッセージ、ブランチなど)は常にすべてのコピーに複製されます」とも言います。。すべてのブランチがあなたのコピーにクローンされている場合、それらの不可解な非ローカルブランチは何ですか?コメント欄で答えるのは複雑すぎるかもしれません。
パイプ

2
@pipe変更をコミットするとき、ローカルコミットを作成してこれを行います。これにより、ブランチが指しているコミットが変更されます。他の人がこれらの変更を取得したい場合は、これらの変更をリモートリポジトリにプッシュする必要があります。これにより、この新しいコミットを指すリモートブランチが作成されます。今、誰もがそこからこれらの変更を引くことができ、結果として誰もが最終的にリポジトリの完全なコピーになるだろう
Frozn

9
@pipe最初に、実際に使用できるのはブランチをクローン化することだけです--single-branch(チップが付いている場合でも--depth 1)。gitに知られているローカルブランチとリモートブランチの違いは、単なるラベルの一種です。リモートブランチには、リモートソースの名前が接頭辞として付けられます(多くの場合origin)。ローカルブランチにはその接頭辞がありません。しかし、最終的には、データはローカルで利用可能になります(あなたが行った--single-branch場合、またはそれに類似した場合を除く)。あなたが実行するとgit checkout $branchname、分岐しているが、ローカルリモートブランチが存在するが、Gitは自動的にリモートを「追跡」ローカルブランチを設定していません。
ジョナスシェーファー

「トランクの上のディレクトリをチェックアウトしない限り」-私の経験では、これは非常に一般的です。なぜなら、マージがずっと簡単になるからです。(バージョンタグの代わりに単一の「ライブ」ブランチを使用しますが、通常はコードのコピーが2〜3個だけです)
-Izkata

1
@Iskata「マージがずっと簡単になります」
-HorusKol

3

これはでタグ付けされているので、SVNの知識の欠如が無視できないことを願っています。

現在、私はリポジトリをクローンし、gitkを使用して特定のブランチをクローンしています。

特定のブランチだけでなく、リモートリポジトリ全体のクローンを作成しています。

リポジトリはデータベースとして最もよく想像されるので、リモートデータベースの現在の状態のクローンを作成しています。しかし、その後は、そのデータベースの独自のコピーに取り組んでいます。コミットすると、ローカルデータベースが変更されます。

このfetchコマンドは、ローカルデータベースをリモートデータベースと同期させるために使用されます。

通常、そのローカルデータベースから、作業するブランチをチェックアウトします。これは、現在の作業が始まったgitの内部マーカーのようなものです。

たとえば、に加えてブランチが存在しない単純なリポジトリに取り組んでいるmasterとしましょう。.git「魔法」を明らかにするためにフォルダを覗いてみてください。

最後のコミット(master)があったと仮定する182e8220b404437b9e43eb78149d31af79040c66と、まさにそれを見つけるでしょうcat .git/refs/heads/master

新しいブランチgit checkout -b mybranchから分岐すると、ファイル内でまったく同じポインターが見つかりますcat .git/refs/heads/mybranch

ブランチは「ポインタ」にすぎません。「作業」マーカーはと呼ばれますHEAD

あなたHEADがどこにいるか知りたい場合:

cat .git/HEADこれは、たとえばref: refs/heads/mybranchcat .git/refs/heads/mybranchコミットハッシュを指す()78a8a6eb6f82eae21b156b68d553dd143c6d3e6f

実際のコミットは、objectsフォルダの下に保存されます(独自のトピックはどのようになりますか)。

プロジェクトフォルダーにはそのブランチのコンテンツのみが含まれており、SVNのようにすべてのブランチを表示することはできません。

working directory全体を「git-database」と混同しないでください。上で述べたように、作業ディレクトリは(たぶん)サブセットのスナップショットにすぎません。

別のブランチがある場合、作業ディレクトリはそのブランチでの作業専用になります(ただし、そこから作業を他の場所に配置できます)。

通常、プロジェクトに定義されているブランチを確認したい場合は、次の可能性があります。

  • git branch 地元の支店向け
  • git branch --remote リモートブランチ用
  • git branch -a 両方のための

(またはgit branch -v

gitは分散バージョン管理システムであるため、ローカル/リモートで異なるブランチを作成することが可能であるだけでなく、推奨されます。

私の典型的なワークフローは次のとおりです。

  • 機能を分岐させる
  • WIP(作業中)ブランチからブランチ
  • あなたが望むように動作します-1行後にコミットしたとしても; 関係ない

機能が完了したら:

  • WIPブランチのスカッシュ/リワーク(インタラクティブなリベースを使用)= そのブランチから単一のコミットを行う
  • WIPブランチを機能ブランチにマージし、それを提供して(githubで作業している場合、そのオファーは「プルリクエスト」と呼ばれます)、安定した(マスター)ブランチに統合します。

また、たとえば、マスターでホットフィックスを作成し、別のブランチのコンテンツも保持する必要がある場合に備えて、2つのブランチで同時にwprlする必要があるプロセスを処理する方法を知りたいです。

プロジェクトの構造に依存します。

安定したマスターがあるとしましょう。また、機能はその安定したブランチからのみ開発されるため、通常は機能ブランチの背後にあります。次に、機能ブランチのルートとなるマスターでの最後のコミットがあります。

次に、マスターブランチでコミットを行い、両方のブランチをマージするかリベースするかを決定できます(これは、高度なニーズを持つユーザーにとっては一種のマージです)。

または、ブランチ(例master)に変更を加えて、他のブランチにチェリーピックすることもできます。

GITのレポジトリからクローンされたブランチを含むフォルダーを作成するための推奨される名前の規則は何ですか、例myproject-branchname

それはあなた次第です。

通常、最終的にリポジトリ名になります。

ただし、これが望ましくない場合もあります。

たとえば、git clone git://github.com/robbyrussell/oh-my-zsh.git ~/.oh-my-zsh here .oh-my-zshがターゲットとして明示的に指定されているoh-my-zshのクローンを作成します。


2

Git clone 実際にはリポジトリ全体を複製しますが、作業ディレクトリをデフォルト(通常はマスター)に設定します。

他のブランチを使用git branchして、ローカルブランチまたはgit branch -rリモートブランチを表示git checkoutし、既存のブランチに切り替えるか、現在のブランチに基づいて新しいブランチを作成することができます。

詳細についてはgitドキュメントをお読みください。Atlassianにも良い記事があります。


0

gitとsvnのブランチは根本的に異なります。

svnでは、ブランチ(またはタグ)はリポジトリ内のディレクトリです。

gitでは、ブランチ(またはタグ)はコミットへのポインターです。

svnを使用すると、レポジトリのルートをチェックアウトしたい場合にできます。これは、すべてのブランチとタグを一度にチェックアウトすることを意味します。これは普通のsvnの使い方ではありません。

gitブランチはディレクトリではないため、「リポジトリのルートをチェックアウトする」ことと同等のものはありません。複数の作業ツリーがサポートされているので、本当に必要な場合はスクリプトをまとめてすべてのブランチを同時にチェックアウトできると思いますが、そうするのはかなり珍しいことです。

さらに、SVNには1つのリポジトリがあります。gitでは、すべての開発者が独自のリポジトリを持っています。これは、開発者がオフラインで作業できることを意味しますが、開発者が異なれば、各ブランチの内容について異なる考えを持つこともあります。

ディレクトリであることと、svnの単純な線形履歴モデルによって、svnブランチには堅牢な履歴があります。日付yのブランチxの内容を知りたい場合は、簡単にその質問をすることができます。

一方、Gitブランチには実際には履歴がありません。「reflog」はありますが、長期的な履歴というよりも災害復旧メカニズムとしての使用を目的としています。特に、reflogはリモートで読み取ることができず、裸のリポジトリではデフォルトで無効になっています。

もちろんコミットには履歴がありますが、それらの履歴は「日付zのリポジトリxのブランチxにあったもの」の質問に答えるのに十分ではありません。

Gitを使用してローカルリポジトリ内のすべてのブランチを表示する簡単な方法が見つかりません。

「git branch」と入力すると、すべてのローカルブランチを一覧表示できます。

「git branch -a」を使用して、ローカルとリモートの両方のすべてのブランチをリストできます。

また、たとえば、マスターで修正プログラムを作成する必要があるが、別のブランチのコンテンツも保持する必要がある場合に備えて、2つのブランチで同時に作業する必要があるプロセスの処理方法を知りたいと思います。

いくつかのオプション。

「他のブランチ」で変更をコミットし、マスターに切り替えてそこで作業を行ってから、元に戻すことができます。

追加の作業ツリーを作成することもできます。構文の詳細については、Googleの「git-worktree」。

Gitのリポジトリからクローンされたブランチを含むフォルダーを作成するための推奨される名前の規則は何ですか(例myproject-branchname)?

私は確立されたコンベンションがあるとは思わない。複数の作業ツリーを一度にチェックアウトすることは、ルールではなく例外です。


2
この答えは不完全に見えます、なぜですか?
グナット
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.