6

git で、次のようにすると、ブランチ マスターとタグ 0.0.1 があるとします。

git checkout 0.0.1
git branch -b random-fix
# some changes...
git checkout master
git merge random-fix

タグからのブランチは、内部的に、ブランチ マスターのタグによってマークされたコミットへの参照を作成します。または、タグがある種のブランチであるかのように、ブランチは「タグ自体」からのものですか?

タグにチェックアウトすると、「切り離された頭」などになるので、これを求めていますよね?それを知って、branch-from-tag について考えました。

4

2 に答える 2

7

タグ リファレンス コミット

タグはコミットへの参照です。具体的には、軽量タグは、ユーザー定義の名前を使用して特定のコミットを指す単なる参照です。例えば:

$ git log
commit e0e92bc337b246696aec5c214507321c7526c1e9
Author: John Doe <john.doe@example.com>
Date:   Thu Sep 26 14:38:36 2013 -0400

    Empty initial commit.

$ git tag v0.0.1

$ cat .git/refs/tags/v0.0.1 
e0e92bc337b246696aec5c214507321c7526c1e9

実際の SHA-1 はどちらの場合も同じです。別の言い方をすれば、タグはコミットへの単なるポインターです。

タグをコミット識別子として使用する

コミット識別子から行うのとまったく同じ方法で、タグから分岐できます。たとえば、次の 2 つのコマンドは事実上同じものです。

  • git checkout -b new_branch v0.0.1
  • git checkout -b new_branch e0e92bc337b246696aec5c214507321c7526c1e9

新しいブランチの開始点がタグ、SHA-1、またはその他の形式のリビジョン選択としてリストされているかどうかは、Git にとって違いはありません。

于 2013-09-26T18:49:34.500 に答える
5

(これはおそらくコメントのはずですが、大きすぎて適切な書式設定が必要です:-) ...また、いくつかのリンクをたどると、私は風変わりな気分になっているようです...)

これを理解するための鍵は、あなたはすでにそこにいると思いますが、次の読者に明確にするために SO の記事に入れましょう。

すべての git ref は、単一のコミットに名前を付ける (指す) ことになります。

これは、タグ (軽量または注釈付き)、ブランチ、「リモート ブランチ」、git「メモ」参照、「スタッシュ」などに当てはまります。それらはすべて 1 つのコミットに名前を付けており、それだけです。(まあ、そうではありません: 技術的には、タグはリポジトリ内の任意のオブジェクトに名前を付けることができます。実際、それが注釈付きタグのしくみです: 注釈付きタグであるリポジトリ オブジェクトに名前を付ける軽量タグがあり、注釈付きタグに名前を付けるcommit オブジェクト. これも仕組みです.HEAD通常は別の ref に名前を付け, それが commit に名前を付けます. そのため, コミットするためにタマネギからいくつかの層を剥がさなければならない場合があります. blob または tree オブジェクトに名前を付けることは可能ですが, 通常は,実際にこれを行うものは何もありません。)

(もちろん、コミットの「本当の名前」は SHA-1 値です。)

ブランチ参照名を「特別」にする理由も同様に単純です。

ブランチ参照は、新しいコミットが追加されたときに、新しいブランチ ヒントに自動的に移動する名前です。

具体的には、フォームの ref は何らかのコミットを指します (名前はコミットを指しているため、定義によります)。そのブランチ1を「オン」にして、またはまたはのような新しいコミットを追加する git 操作を実行すると、git は新しいコミットをリポジトリに貼り付け、名前を新しいコミットに再ポイントします。それだけです。refs/heads/branchnamegit commitgit mergegit cherry-pick

私たちが「ブランチ」と考えるものは、先端 (名前が指すコミット) から開始し、各コミットの親または親を使用して逆方向に作業することによって形成されます。コミットに親が 1 つある場合、それは「ブランチ上」の通常のコミットです。2 つ以上ある場合、それは「マージ」であり、すべての親をたどってマージされたものを見つけることができます。親がまったくない場合、それはルート コミットです (新しいリポジトリの最初のコミットのように、実際には複数のルートを持つことができます。たとえば、git "notes" はこれを行います)。

1 つのコミットに 7 つのブランチ ラベルを付けると、「ブランチ」の2 つの名前が 7 つになります。これを 1 つに絞れば、もちろん混乱は少なくなりますが、git はどちらの方法も気にしません。(Git は、名前がゼロになるかどうかだけを気にします。ブランチはまだ存在しますが、見つけるのは非常に難しく、ガベージ コレクションの対象となります。)

話題になっているので、「リモートブランチ」についてもメモしておきます。(「リモート ブランチ」という名前に完全に満足したことはありませんが、より良い名前がないので、定義しておきましょう。) 「リモート ブランチ」は、形式のローカルリファレンスです。ここで、rname はの名前です。リモート ( など) であり、bnameはリモートのブランチ名です。つまり、そのリモートにログインしてそこのブランチを見た場合に続く部分です。リモートブランチを「オン」にすることはできません—もしそうなら、gitは「切り離されたHEAD」を提供します—しかし、これらのブランチ名自動的に更新されます:refs/remotes/rname/bnameoriginrefs/heads/git checkout origin/mastergit fetchリモートから新しいコミットを取得するには、新しいブランチ ヒントも取得します。言い換えれば、名前を新しいブランチのヒントに移動する代わりに、他の誰かに (リモートで) 移動させてから、フェッチするときに最新バージョンを一度に取得します。


1「ブランチ上」にあるためには、HEADref は のような「間接」参照でなければなりませんref: refs/heads/masterHEAD代わりに「切り離された」場合、未加工の SHA-1 値が含まれます。コミットを追加することはできます。ラベルのないブランチに追加されます。の参照により、HEADガベージ コレクションが行われなくなります。

2タグがあればそれ以上。タグがないと仮定しましょう。

3脚注 3 はありません。

于 2013-09-27T02:03:16.760 に答える