1

今日、私は自分のプロジェクトの 1 つに取り組んでいて、git の奇妙な点に気付きました。Git を使用すると、作業をゴースト ブランチにコミットできます。ゴースト ブランチという用語を使用するのは、変更がツリーのどこかに存在するが回避するためgit log --graph --decorate --oneline --allです。誰かが私にこれがなぜなのか説明できますか?

この動作を再現する手順

頭が切り離された状態に入る( を実行すると、そこに入ることができますgit checkout <hash>)。

# Not currently on any branch.
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   uml 1.pdf

コードベースにいくつかの変更を加えます。を使用して、作業ディレクトリのステータスを確認しますgit status。これにより、変更がリストされますが、どのブランチにもいないことが示されます。

# Not currently on any branch.
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   .gitignore
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#   uml 1.pdf

を使用して変更をコミットしますgit commit -am '<message>'

[detached HEAD ded7725] updated .gitignore
 1 files changed, 8 insertions(+), 1 deletions(-)

次に、たとえば「マスター」などの既知のブランチをチェックアウトすると、切り離されたヘッド状態でコミットされたすべての変更が失われます。これは予期されることです。

Runnigは、デタッチされたヘッドでコミットされたものを除くgit log --graph --decorate --oneline --allすべてのコミットを表示します(私の場合)。ded7725

ただし、agit checkout <hash-for-ghost-branch>はゴースト ブランチにコミットされた変更を返します。問題は、このハッシュを永遠に覚えていられないことです。

予想される動作は、このゴースト ブランチがグラフのログ上でややぶら下がっているリーフになることです。しかし、それは存在しません。なぜこれが起こるのかについての説明をいただければ幸いです。または、非表示のブランチを表示するフラグを見逃している可能性があります...

4

3 に答える 3

2

「ゴースト」ブランチと呼ばれるものは、ブランチではありません。これは、何も指されていない DAG のコミットです。

私はコードを見ていませんが、git log がグラフを描画し、ブランチ ポインターから開始して逆方向に作業することでコミットを一覧表示すると想像できます。デタッチされた HEAD 状態のコミットには何も指していないため、git log がそれらを「見る」方法はありません。

これを修正するには、単純に でブランチを作成しgit branch branch_name <commit>ます。次に、git log には、デタッチされた HEAD 状態で行われた最後のコミットを指すものがあり、ログを表示したりグラフを描画したりするときに、それらのコミットを「検索」します。

于 2012-07-25T21:16:28.317 に答える
2

この「ゴースト」ブランチが git ログ --all に表示されない根本的な理由は、このログが既存のすべてのコミットではなく、すべてのブランチのみを表すためです。コミットをリベースするときは、古いコミットを削除せず、それらを別の親にコピーするだけであることを考慮する必要があります。そのため、ゴースト ブランチのように、ブランチなしでコミットすることもできます。

コミットは、他のオブジェクトによって参照されるオブジェクトのようなものです。git によって保持される唯一のオブジェクトは、ブランチによって参照されるオブジェクトです。これはガベージ コレクション メモリのようなものです。コミットは、参照せずにメモリ内に作成したオブジェクトです。git を実行するgit gcと、「ゴースト ブランチ」を含め、どのブランチからも参照されていないこれらのコミットがすべて削除されます。

解決策は、wasworld で説明されているようにブランチを作成するか、 commit にタグを付けて、このコミットへの参照を保持することgit tag tagname sha1です。

編集:git gcマニュアルページによると、最近のコミットは削除されません:

The optional configuration variable gc.reflogExpire can be set to indicate how long 
historical entries within each branch's reflog should remain available in this 
repository. The setting is expressed as a length of time, for example 90 days or 3
months. It defaults to 90 days.

したがって、ゴースト ブランチはgit gc、デフォルトで 90 日間安全です (要求しなくても開始できます)。

于 2012-07-25T21:36:21.943 に答える
1

git ブランチでは、コミットへの単なるポインターです。では、「問題は、このハッシュを永遠に覚えておくことはできない」と言うとき、そこにブランチを作成しないのはなぜですか?

git branch branch_name <commit>

また、このコミットを指すブランチを作成しない場合、有効期限が過ぎると GC されることにも注意してください。デフォルトは 90 日です。

于 2012-07-25T21:31:44.300 に答える