切り離されたHEAD状態で作成されたgitコミットはどうなりますか?


137

これが起こったことです:

私はブランチAを持っています。ブランチでは、AIが一連の変更をコミットしました。コードに満足できなかったので、ブランチAで以前のコミットをチェックアウトしました。次に、さらに多くの変更を加え、ブランチAでコミットしました。このコミットはどこにも見つかりません。このコードを紛失しましたか?


「ブランチAで以前のコミットをチェックアウトした」と言うとき、「ブランチAを以前のコミットにリセットした」という意味ですか?つまり、あなたは実際にgit resetではなくgit checkout
CBベイリー

いいえ、チェックアウトを使用しました。reflogが機能しました。
Mausimo 2012

チェックアウトを使用した場合は、デタッチされておりHEAD、ブランチAは以前のコミットのままでした。正確にどのコマンドを実行しましたか?
CBベイリー

1
OSX LionでSourceTree GIT GUIを使用していました。私はブランチAにいて、ブランチAで以前のコミットのチェックアウトを実行しました。次に、コードを変更してコミットしました(ブランチA)。頭が離れていたと思います。
Mausimo 2012

OK、ブランチAでさらに多くの変更をコミットしたと言ったとき、私は混乱したと思います。
CBベイリー

回答:


185

古いコミットはまだreflogにあります。

git reflog

これにより、コミットのリストが表示され、「失われた」コミットがそこにあるはずです。新しいブランチにすることができます。たとえば、SHA-1がba5a739の場合、次のコマンドを使用して、古いコミットで「new-branch」という名前の新しいブランチを作成できます。

git branch new-branch ba5a739

「失われた」コミットは、データベースが整理されるときに削除されることに注意してください。


3
私は同じことをしました、そしてそれが失われたと思って心臓発作を起こしました。情報をありがとう!
チェイス

14
git cherry-pick [SHA]切り離されたヘッド状態で誤ってコミットした場合に備えて、コミットを既存のブランチに移動するために使用します
Jan Aagaard Meier '20

3
または、既存のブランチに切り替えて、reflogにリストされている「失われた」コミットに対応する「git merge HEAD @ {n}」nを実行できます。
eaykin

pruneがコミットメッセージで参照されている分離されたコミットも削除するかどうかを知っていますか?それとも、それらを到達可能にしますか?
カマフェザー

@Kamafeather:それが彼らを到達可能にするとは思いません。
ディートリッヒエップ2018

63

すでに指摘したように、コミットはreflogで引き続き利用できます。他の答えに加えて、新しいブランチを作成してマージせずに、切り離されたHEADコミットを現在のブランチに直接引き継ぐ方法があります。

  1. 切り離されたHEAD状態で行ったコミットのSHA-1ハッシュを検索します。

    git reflog
    
  2. 次に、すべてのコミットハッシュを古いものから新しいものへと並べて実行します。

    git cherry-pick <hash1> <hash2> <hash3> ...
    

    たとえば、「最初の7文字」の短いハッシュ形式で1つしかなかった場合:

    git cherry-pick a21d053
    

これにより、現在のブランチへの新しいコミットが作成されます。コマンドで指定したdetached-HEAD-commitハッシュごとに1つのコミットが作成されます。また、元のコミットメッセージを引き継ぎます。


11

次のコマンドを使用すると、失われた(ぶら下がっている)コミットを見つけることができます。

git fsck --lost-found

現在のヘッドがぶら下がっているコミットの場合、失われたものとしてリストされないことに注意してください。

詳細はgit-fsck(1)マニュアルページをご覧ください。

次に、失われたコミットにブランチを作成します。

git branch new-branch ba5a739

最初にコマンド「git reflog」を使用し、次に「git branch new-branch ba5a739」をサブモジュールに使用しました。
ondermerol

7

作業ディレクトリの状態のGit用語は「切り離されたヘッド」です。ここにgit reflog保存を行う別の場所があります。

$ git reflog
0b40dd6 HEAD@{0}: commit: my commit on detached HEAD
...

別のブランチをチェックアウトしようとすると、git-1.7.5.1が役立ちます。

$ gitチェックアウトマスター
警告:1つのコミットを残し、接続されていません
あなたのブランチのいずれか:

  0b40dd6デタッチされたヘッドでのコミット

新しいブランチを作成してそれらを保持したい場合、これは良いタイミングかもしれません
これを行うには:

 git branch new_branch_name 0b40dd65c06bb215327863c2ca10fdb4f904215b

ブランチ「マスター」に切り替え

情報とリンクをありがとう。リンクは私が何が起こっていたかを理解するのに役立ちました。
Mausimo 2012

6

あなたはそれを失いませんでした、Gitはまだコピーを保持しています(しかし、それは現在どのブランチヘッドからも到達不可能です)。git reflogコマンドを使用して、不足しているコミットを見つけることができます。reflogはブランチヘッドの履歴位置を追跡します。これを使用して、ブランチヘッドが以前に指していたものを見つけることができます。


4

次の手順に従って、切り離したヘッドをgit repoにリンクします

  1. git checkout "your branch with path but without remote name"

たとえば、リモート名がoriginであり、ブランチ名がbugfix/somebranch使用されている場合git checkout bugfix/somebranch

  1. git reflog デタッチされたブランチのコミットリストからリストされたコミットSHAを取得します。

  2. git cherry-pick "commit hash1" "commit hash2" "commit hash3"

  3. git push

準備完了!!


2

Sourcetreeでgit reflogが機能しないことがわかったので、GUIを使用してこれを行う方法を見つけました。

最初に、コマンド履歴(view:Show Command Output)でメッセージを探して、「失われた」コミットを見つけようとします。うまくいけば、失われたコミットの後に「Switching Branch」というコマンドに入れられ、1234567のコミットIDを持つコミットコメントが表示されます。

そのコミットIDを次のステップに進めます。

トップツールバーの「ブランチ」ボタンを押すと、特定のコミットを指定できるダイアログ「新しいブランチ」が表示されます。そこにそのコミットIDを入力し、新しいブランチ名を指定して、Create Branchをクリックすると、失われたコミットで新しいブランチを取得できます!

これは私にとって失われた仕事をもたらしました!

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