Git分離ヘッドを修正しますか?


1455

私は私のリポジトリでいくつかの作業をしていて、ファイルにローカルな変更があることに気づきました。もう必要ないので、新しいコピーをチェックアウトできると思ってファイルを削除しました。私はGitと同等のことをしたかった

svn up .

を使用git pullしてもうまくいかなかったようです。いくつかのランダム検索で、誰かが推奨するサイトに私を導きました

git checkout HEAD^ src/

srcは、削除されたファイルを含むディレクトリです)。

今私は分離した頭を持っていることがわかりました。それが何であるか私にはわかりません。どうすれば元に戻すことができますか?


69
git checkout masterマスターブランチに戻ります。作業コピーの変更をクリアしたい場合は、おそらく実行したいと思いますgit reset --hard
Abe Voelker


あなたがコミットしていないなら、あなたはそうすることができましたgit checkout -- src/
thesummersign

これを試してください:リンク。要するにcreate temp branch - checkout temp branch - checkout master - delete temp branch
fidev

@AbeVoelkerコメントでどういう意味working copy changesですか?別のコミットをチェックアウトした後にファイルに加えた変更(つまり、ヘッドが切り離された状態で行った変更)を参照していますか?
Minh Tran

回答:


2148

分離したヘッドは、ブランチにいないことを意味します。履歴内の単一のコミット(この場合、HEADの前のコミット、つまりHEAD ^)をチェックアウトしました。

デタッチされたHEADに関連する変更を削除する場合

あなたはあなたがいたブランチをチェックアウトするだけです、例えば

git checkout master

次にファイルを変更し、それをインデックス内の状態に復元したい場合は、最初にファイルを削除せずに、

git checkout -- path/to/foo

これにより、ファイルfooがインデックス内の状態に復元されます。

デタッチされたHEADに関連付けられた変更を保持したい場合

  1. 実行git branch tmp-これはと呼ばれる新しいブランチに変更を保存しますtmp
  2. 走る git checkout master
  3. に加えた変更を組み込みたい場合は、ブランチからmaster実行git merge tmpmasterます。master実行後はブランチにいるはずgit checkout masterです。

6
「これにより、ファイルfooは、変更を加える前の状態に復元されます。」-> インデックス内の状態に復元します -編集してください
Mr_and_Mrs_D 2013

88
なぜ最初にこのエラーが発生するのですか?これは私がgitを嫌うものの1つです-時々完全にランダムな動作です。Mercurialでこのような問題が発生したことはありません。
バイオレットキリン

97
@VioletGiraffeこれはエラーではなく、ランダムなものでもありません。これは、前のコミットをチェックアウトしたときにリポジトリが入る状態にすぎません。「切り離されたヘッド」は、そのポイントから作業を行うつもりであれば、ブランチを作成したり、ブランチをポイントしたりすることもできるという警告として機能します。ただし、そのタグを表示またはコミットするだけの場合は、ヘッドが切り離された状態であることには何の問題もありません。
Neil Neyman、2014年

22
切り離された頭にコミットしている場合は、これを行わないでください。他の回答を参照してください。もしそうなら、あなたは前のgitの言及をチェックアウトできますPrevious HEAD position was 7426948...
KCD

9
@VioletGiraffe:Mercurialに基づいて何が起こっているかについてのメンタルモデルがありますが、Gitを使用しています。Gitのモデルに合わせてメンタルモデルを調整したくない場合は、ランダムに表示されます。それは、VRゴーグルをつけたまま外を歩いているようなもので、飛行機を飛ばしているように見えますが、実際には通りを渡っています。あなたは車にひかれるでしょう。
iconoclast

477

失いたくないファイルを変更した場合は、それらをプッシュできます。私はそれらを分離モードでコミットしました。その後、一時的なブランチに移動して、後でマスターに統合できます。

git commit -m "....."
git branch my-temporary-work
git checkout master
git merge my-temporary-work

から抽出:

デタッチされたヘッドで行われたコミットをどうするか


27
私はこれが好ましい解決策だと思っています-特に、個々のバージョンをチェックアウトしたときに加えた変更を保持したい場合は。
adswebwork 14年

10
@adswebwork:同意する。他のすべての回答は、以前の状態に戻し、分離されたヘッド状態でローカルに行われた変更を失うことを示唆しています。
Sk8erPeter 2014年

6
なんでgit stash?それが私の頭に浮かぶ最初のものですので。新しいブランチを作成するのはやりすぎです。
thesummersign

2
またgit rebase my-temporary-work、ブランチを削除git branch -d my-temporary-workして、最初から正しいブランチにコミットしたように見せることもできます。
ゾルタン

@geekay git stashは、このケースに最適なツールのように聞こえます。それを達成するために提案された手順で答えを書いていただけませんか?
ゾルタン

157

一時的なブランチを作成しないソリューション。

このモードですでに何かを変更し、オプションで変更を保存したい場合に、デタッチされたHEAD状態を終了(「修正」)する方法:

  1. 保持したい変更をコミットします。デタッチされたHEAD状態で行った変更を引き継ぐ場合は、それらをコミットします。お気に入り:

    git commit -a -m "your commit message"
    
  2. 保持したくない変更を破棄します。ハードリセットは、デタッチされたHEAD状態で行ったコミットされていない変更を破棄します。

    git reset --hard
    

    (これがないと、ステップ3は失敗し、デタッチされたHEAD内の変更されたコミットされていないファイルについて不満が出ます。

  3. ブランチをチェックしてください。以前に作業したブランチをチェックアウトして、デタッチされたHEAD状態を終了します。次に例を示します。

    git checkout master
    
  4. コミットを引き継ぎます。別の質問への私の回答に示すように分離されたHEAD状態で行ったコミットをチェリーピックすることで引き継ぐことができます。

    git reflog
    git cherry-pick <hash1> <hash2> <hash3> …
    

git reset --hardアップストリームをソースにしてローカルの変更を削除する必要があるため、これはまさに必要でした。
Markus Zeller、

すばらしい答え、これは私にとって
うまくいっ

130

分離したヘッドとは:

  1. あなたはもう枝にはいません
  2. 履歴で1つのコミットをチェックアウトしました

変更がない場合:次のコマンドを適用してマスターに切り替えることができます

  git checkout master

保持したい変更がある場合:

デタッチされたHEADの場合、名前付きブランチが更新されないことを除いて、コミットは通常のように機能します。コミットされた変更でマスターブランチを更新するには、現在の場所に一時ブランチを作成し(このようにして、一時ブランチには、切り離されたHEADで行ったすべてのコミット済み変更が含まれます)、マスターブランチに切り替えて、一時ブランチをマスター。

git branch  temp
git checkout master
git merge temp

2
完璧、それからブランチ一
Davi Menezes

64

これは、私が分離した頭の上にいて、すでにいくつかの変更を行っていることに気付いた直後のことです。

変更をコミットしました。

$ git commit -m "..."
[detached HEAD 1fe56ad] ...

コミットのハッシュ(1fe56ad)を思い出しました。それから私は私がいたはずのブランチをチェックアウトしました。

$ git checkout master
Switched to branch 'master'

最後に、コミットの変更をブランチに適用しました。

$ git cherry-pick 1fe56ad
[master 0b05f1e] ...

これは一時的なブランチを作成するよりも少し簡単だと思います。


2
これが答えになるはずです。それはあなたの裸のファイルを取り戻します。
BlindWanderer 2014年

2
はい、これは実際に行うのが最も簡単なことです。次回発生したときにWebを検索しなくても覚えておくのに十分なほど簡単です。コミットし、ハッシュを書き留め、コミットするつもりだったブランチに戻りますgit cherry-pick <hash>
メイソン

解決策をありがとう。これは役に立ちました。私のマスターとorigin / masterが同じコミットを指すように「git push origin master」を実行する必要があったことも追加できますか。
turnip424 2018年

1
これは本質的にタニウスの答えです(1年以上前に投稿されました)。
Peter Mortensen、

この陽気なピックのおかげで、デタッチヘッドの最後の変更を元に戻します
オメガキューブ

55

いくつかの変更を行った後、分離したヘッドを使用していることに気付いた場合、そのための簡単な解決策があります:stash-> checkout master-> stash pop:

git stash
git checkout master   # Fix the detached head state
git stash pop         # Or for extra safety use 'stash apply' then later 
                      #   after fixing everything do 'stash drop'

何も起こらなかったように、コミットされていない変更と通常の「アタッチされた」HEADがあります。


2
このバッドボーイをブックマークしました-一時的なブランチを作るのを節約します。御馳走を働いた。
Tim Tyler、

1
gitサブモジュールをチェックアウトして変更を加えた後、分離したHEAD状態になることがよくあります。これは、変更を保存できるようにするために、修正するための最良かつ最も簡単なソリューションであることがわかりました。
user5359531 2018年

1
デタッチされた状態ですでに変更をコミットしている場合、これは機能しませんか?
Danijel

40

で特定のコミットをチェックアウトするとgitヘッド切り離された状態になります。つまり、作業コピーは名前付き参照(「マスター」など)の状態を反映しなくなります。これは、リポジトリの過去の状態を調べるのに役立ちますが、実際に変更を元に戻そうとしている場合は、必要なものではありません。

特定のファイルに変更を加えて、それらを単に破棄したい場合は、checkout次のようなコマンドを使用できます。

git checkout myfile

これにより、コミットされていない変更が破棄され、ファイルが現在のブランチの先頭にある状態に戻ります。すでにコミットした変更を破棄したい場合は、resetコマンドを使用できます。たとえば、これはリポジトリを以前のコミットの状態にリセットし、その後の変更をすべて破棄します。

git reset --hard HEAD^

ただし、リポジトリを他の人と共有している場合、git resetは混乱を招く可能性があります(リポジトリ履歴の一部が消去されるため)。既に他の人と変更を共有している場合は、通常、git revert代わりに確認する必要があります。これにより、「アンチコミット」が生成されます。つまり、問題の変更を「取り消す」新しいコミットが作成されます。

Git Bookに詳細があります。


1
@ralphtheninjaの回答で述べたように、とgit checkout path/to/foo競合する可能性があるため、これらの競合を回避するためgit checkout some-branchに使用git checkout -- path/to/fooする方が良いでしょう。
ディエゴラゴ

30

HEADはポインター内にあり、その結果、特定のコミットを(直接的または間接的に)指します。

アタッチされた   HEADは、ブランチにアタッチされている(つまり、ブランチを指している)ことを意味します。
切り離された HEADは、どのブランチにも接続されていないことを意味します。つまり、いくつかのコミットを直接指します。

ここに画像の説明を入力してください

言い換えると:

  • コミットを直接指す場合、HEADは切り離されます。
  • 間接的にコミットを指す場合(つまり、ブランチを指し、次にブランチがコミットを指す場合)、HEADがアタッチされます。

ヘッドの取り付け/取り外しの状況をよりよく理解するために、上の写真の4つ組に至るまでの手順を示しましょう。

リポジトリの同じ状態から始めます(すべての象限の画像は同じです)。

ここに画像の説明を入力してください


ここで、実行する必要がありますgit checkout—個々の画像の異なるターゲットを使用して(それらの上のコマンドは淡色表示され、これらのコマンドのみ適用することを強調しています):

ここに画像の説明を入力してください


これらのコマンドを実行したの状況は次のとおりです。

ここに画像の説明を入力してください

ご覧のように、HEAD はコマンドのターゲットを指しますgit checkoutブランチ(4つ組の最初の3つのイメージ)、または(直接)コミット(4つ組の最後のイメージ)を指します。

作業ディレクトリの内容も変更され、適切なコミット(スナップショット)、つまりHEADによって(直接または間接に)コミットが指定されるようになります。


これで、この回答の最初と同じ状況になりました。

ここに画像の説明を入力してください


6
読みませんでしたが、あなたが作った素敵な写真に賛成票を投じました;)
カルロウッド

@Carlo、ありがとう!
MarianD

22

"detached head state"はtempブランチを使用しgit checkout -ているので、使用した最後のブランチに移動するだけを使用します。


1
注意してください。デタッチされたヘッド状態のときに行ったコミットは失われます。
Ajak6 2017

@ Ajak6これらのコミットを失うことはありません。それらはまだ経由git reflogして利用可能であり、新しいブランチまたはgit cherry-pick既存のブランチに引き継ぐことができます。この質問を参照してください。
タニアス

7

@Philippe Gerberの回答をさらに明確にするために、ここに示します。

gitチェリーピック

以前は、この場合はcherry-picka git checkout masterが必要です。さらに、それはcommitinでのみ必要ですdetached head


6

補遺

戻りたいブランチが最後に行ったチェックアウトである場合、単にを使用できますcheckout @{-1}。これにより、以前のチェックアウトに戻ります。

さらに、たとえば、このコマンドをエイリアス化して、入力git global --config alias.prevするだけでgit prev前のチェックアウトに戻ることができます。


4

「切り離されたヘッド」にあるということは、HEADが特定の名前のないコミットを指すことを意味します(名前付きブランチとは対照的に)(cf:https : //git-scm.com/docs/git-checkout section Detached head

問題を修正するには、以前に選択されたブランチを選択するだけです

git checkout @{-1}


2

ヘッドが切り離された状態で新しいファイルを作成した場合は、まず、これらの新しいファイルがインデックスに追加されていることを確認します。たとえば、次のようにします。

git add .

ただし、既存のファイルのみを変更または削除した場合は、次のようにして追加(-a)とメッセージ(-m)を同時にコミットできます。

git commit -a -m "my adjustment message"

次に、現在の状態で新しいブランチを作成するだけです:

git checkout -b new_branch_name

新しいブランチが作成され、すべての調整がその新しいブランチに反映されます。その後、必要に応じて、リモートへのプッシュ、および/またはチェックアウト/プル/マージを続行できます。


1

Gitはそれを行う方法を教えてくれました。

入力した場合:

git checkout <some-commit_number>

ステータスを保存

git add .
git commit -m "some message"

次に:

 git push origin HEAD:<name-of-remote-branch>

1

変更を保持したかったので、これを修正するだけです...

git add .
git commit -m "Title" -m "Description"
(so i have a commit now example: 123abc)
git checkout YOURCURRENTBRANCH
git merge 123abc
git push TOYOURCURRENTBRANCH

それは私のために働く


1

通常HEADはブランチを指します。ブランチを指しているのではなく、コミットハッシュを指しているとき69e51は、分離したHEADがあることを意味します。問題を修正するには、ブランチを2つポイントする必要があります。あなたはそれを修正するために2つのことをすることができます。

  1. git checkout other_branch //そのコミットのコードが必要な場合は不可能 hash
  2. 新しいブランチを作成し、新しく作成したブランチをコミットハッシュにポイントします。

HEADはブランチを指す必要があり、コミットハッシュは絶対的なルールではありません。


これが私がこのエラーを起こした理由です。リビジョンにチェックアウトし、ブランチにチェックアウトするのではなく、現在/最新のリビジョンにチェックアウトしました。助けてくれてありがとう。
Rahul Thakur

1

分離したヘッドは、ブランチを適切にチェックアウトしていないか、単一のコミットをチェックアウトしたことを意味します。

このような問題が発生した場合は、まずローカルの変更を隠して、変更が失われないようにします。

その後...コマンドを使用して目的のブランチをチェックアウトします。

MyOriginalBranchブランチが必要だとします。

git checkout -b someName origin / MyOriginalBranch




0

私の場合、実行するgit statusと、作業ディレクトリに追跡されていないファイルがいくつかあることがわかりました。

実行したいリベースを実行するために、それらをクリーンアップする必要がありました(必要がないため)。


0

これは私にとってはうまくいきます、それは切り離されたヘッドに新しいブランチを割り当てます:

git checkout new_branch_name detached_head_garbage_name


0

切り離されたHEADは、現在どのブランチにもいないことを意味します。現在の変更を保持し、単に新しいブランチを作成する場合は、次のようにします。

git commit -m "your commit message"
git checkout -b new_branch

その後、この新しいブランチを他のブランチとマージしたい場合があります。常に役立つのはgit "a dog"コマンドです。

git log --all --decorate --oneline --graph
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.