現在、別のgit commit(同じブランチで...実際にはmasterブランチで!)に切り替えるために、コマンドを実行しています
git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a
さて、私がこのgitを実行するたびに、私は今、頭が離れていることがわかります。古いコミットに移動し、同じブランチでヘッドを維持するにはどうすればよいですか?
現在、別のgit commit(同じブランチで...実際にはmasterブランチで!)に切り替えるために、コマンドを実行しています
git checkout ea3d5ed039edd6d4a07cc41bd09eb58edd1f2b3a
さて、私がこのgitを実行するたびに、私は今、頭が離れていることがわかります。古いコミットに移動し、同じブランチでヘッドを維持するにはどうすればよいですか?
git checkout
他には、コミットまたは支店名がその新しい場所にヘッドを移動します)。
git revert --no-commit 0766c053..HEAD
これを0766c053
実行します。チェックアウトするコミットはどこにありますか。これはstackoverflow.com/a/21718540/525872からのものです。
回答:
そのコミットをチェックアウトするときに何をしたいかによって異なります。そのリビジョンをビルドまたはテストできるようにチェックアウトするだけであれば、取り外したヘッドで作業しても問題はありません。コミットを行う前に(git checkout master
たとえば)実際のブランチをチェックアウトすることを忘れないでください。そうすれば、どのブランチにも含まれていないコミットを作成することはありません。
ただし、その時点からさらにコミットを行う場合は、ブランチを作成する必要があります。ブランチによって参照されていないコミットを行うと、それらは簡単に失われる可能性があり、何も参照していないため、最終的にgitのガベージコレクターによってクリーンアップされます。次のコマンドを実行して、新しいブランチを作成できます。
git checkout -b newbranch ea3d5ed
視覚化に役立てるために、切り離されたヘッドでの作業とブランチでの作業の違いを示す図をいくつか示します。
master
A、B、Cの3つのコミットから始めましょう。master
現在のブランチなのでHEAD
、master
C.をコミットしている点を、
ABC *-*-* <-マスター<-HEAD
ここでコミットすると、gitはCを親として持つコミットを作成し(これは現在のコミットであり、HEAD
viaからポイントされているためmaster
)、master
その新しいコミットを指すように更新されます。私たちのコミットはすべてに今あるmaster
、そしてHEAD
新しいのポイントが通じコミットmaster
。
あいうえお *-*-*-* <-マスター<-HEAD
それでは、Bをチェックして、切り離されたを与えましょうHEAD
。
あいうえお *-*-*-* <-マスター ^ \ - 頭
ここではすべてが正常に機能します。すべてのファイルを調べたり、プログラムをビルドしたり、テストしたりすることができます。新しいコミットを作成することもできます。しかし、そうすると、現在のブランチがないため、その新しいコミットでブランチを指定することはできません。それを指している唯一のものはHEAD
:
あいうえお *-*-*-* <-マスター \ * <-HEAD E
後でmaster
もう一度チェックアウトすることにした場合、Eを参照するものは何もありません。
あいうえお *-*-*-* <-マスター<-HEAD \ * E
それを参照するものがないため、見つけるのが難しい場合があり、gitは参照のないコミットを放棄されたと見なします(リベースしたり、パッチを押しつぶしたり、その他の楽しい履歴操作を行ったりすると、通常は放棄されたパッチを表します。あなたがもう気にしないこと)。一定の時間が経過すると、gitはそれをガベージと見なし、次にガベージコレクションが実行されたときに破棄されます。
したがって、ベアリビジョンをチェックアウトしてヘッドを切り離す代わりに、より多くのコミットを行う予定がある場合はgit checkout -b branch B
、ブランチを作成してチェックアウトする必要があります。コミットはブランチに含まれるため、簡単に参照して後でマージできるため、コミットが失われることはありません。
あいうえお *-*-*-* <-マスター ^ \-ブランチ<-HEAD
これを忘れて、ブランチからコミットを作成する場合でも、心配する必要はありません。でヘッドリビジョンを参照するブランチを作成できますgit checkout -b branch
。すでにmaster
ブランチに戻っており、迷子のコミットを忘れていることに気付いた場合はgit reflog
、を使用して見つけることができます。これにより、HEAD
過去数日間にコミットが指し示した履歴が表示されます。まだreflogに残っているものはガベージコレクションされず、通常、参照は少なくとも30日間reflogに保持されます。
HEAD
は、コミットを指すブランチを指すのではなく、コミットのSHA-1を直接指す参照があることを意味します。あなたの頭はブランチを参照していないので、Gitは新しいコミットを追加するときにどのブランチを更新するかを知りません。回答の冒頭で説明したように、コードをビルドまたはテストするためだけに古いバージョンに戻る場合は、ヘッドを切り離してもまったく問題ありません。いつでもブランチなどに戻ることができますgit checkout master
。頭が外れているときにコミットした場合にのみ問題になります。
GitのHEADは、作業ディレクトリの内容を示す単なるポインタです。ブランチのヘッドではないコミットをチェックアウトしたい場合は、そのコミットを指すようにHEADをリダイレクトする必要があります。それを回避する方法はありません。そのコミットで一時ブランチを作成できますが、それでもHEADはマスターから離れるように指示されます。
それは簡単な説明です。以下の冗長性は、HEADとmasterの違いを理解するのに役立つことを願っています。
通常、次のようになります。
C ← refs/heads/master ← HEAD
↓
B
↓
A
つまり、「Cの親はBであり、Bの親はAです。ブランチマスターはCを指しています。現在、マスターの内容を確認しています。また、コミットするとマスターが更新されます。」
これには、コミットグラフを完全に理解するために必要ないくつかの仮定が暗黙的に含まれています。つまり、コミットはその親のみを参照し、ブランチの内容は、親リンクをたどることによって到達できるコミット(およびそれらのコミットのみ)です。作業ツリーとインデックスの(変更されていない)コンテンツは、間接的(「シンボリック」)または直接(「デタッチ」)のいずれかで、HEADによって指定されたコミットに対応している必要があります。
したがって、古いコミットをチェックアウトする場合は、目的のコミットを指すようにHEADを更新する必要があります。git-checkout
まさにそれをします:
C ← refs/heads/master
↓
B ← HEAD
↓
A
今、あなたは古いものを見ているので、あなたはあなたの後ろにあなたの枝を残しました。「切り離された頭」のアドバイスが落ち着いて教えてくれるので、それは完全に大丈夫です(私の強調):
周りを見回して実験的な変更を加えてコミットすることができます。また、別のチェックアウトを実行することで、ブランチに影響を与えることなく、この状態で行ったコミットを破棄できます。
一方、ブランチをリセットすると、必要な場所にHEADが表示されますが、効果は大きく異なります。
C
↓
B ← refs/heads/master ← HEAD
↓
A
コミットCは、マスターブランチの一部になりたくないと宣言したため、ガベージになります。
要するに、あなたがしなければならないのは、gitが「HEAD」によって何を意味するかを理解することです—それはあなたがいる場所であり、与えられたブランチがどこにあるかではありません。そして、あなたがいる場所がブランチがある場所と同じでない場合は、切り離されたHEADを使用する以外に選択肢はありません。
(HEADの脱線が続く場合は、GitHub、gitk、またはgitwebを調べて、コミット履歴を参照することもできます。)
私はあなたの質問を理解していると思います。これが私がそれを解決するために見つけたものです。そしてそれのGUIソリューションはありません、あなたはそれを解決するためにコマンドを使うことができるだけです、そしてそれは本当に簡単です。
ステップ1:戻りたい古いコミットのタグを作成します。
タグv2.0のように
ステップ2:git checkout v2.0
これで、HEADは「v2.0」コミットを指していますが、マスターはまだ最後のコミットを指しています。
C:\Program Files\Git\doc\git\html\git-checkout.html
このドキュメントはあなたを助けるかもしれません
または、git help <checkout>と入力します