HEADを以前の場所に戻すにはどうすればよいですか?(切り離されたヘッド)&コミットを元に戻す


179

Gitではsquash commit、別のブランチにマージしてHEADから、次の方法で前の場所にリセットすることで、

git reset origin/master

しかし、私はこれから抜け出す必要があります。HEADを前の場所に戻すにはどうすればよいですか?

23b6772移動する必要があるコミットのSHA-1フラグメント()があります。このコミットに戻すにはどうすればよいですか?


12
HEADは、現在の場所(または正確にはリビジョン)へのポインタにすぎません。git checkout 23b6772すべきです
Yaroslav管理者


1
@YaroslavAdminいいえ、それはすべきでありませ。コミットを直接チェックアウトすることデタッチされたHEAD状態が発生した理由です(リモートトラッキングブランチは自分自身でチェックアウトできず、OPのようにそうしようとすると、ポイントするコミットを自動的に遅延するため)。コメント:-) 最初の問題がすでに解決されていることを願っています...
RomainValeri

回答:


397

答える前に、背景を追加して、これHEADが何であるかを説明しましょう。

First of all what is HEAD?

HEAD現在のブランチ上の現在のコミット(最新)への参照です。
常に1つしか存在できませんHEAD(を除くgit worktree)。

の内容HEADは内部に格納され.git/HEAD、現在のコミットの40バイトのSHA-1が含まれています。


detached HEAD

最新のコミットを行っていない場合、つまりHEAD、履歴内の以前のコミットを指している場合は、と呼ばれdetached HEADます。

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

コマンドラインでは、次のようになります- HEADは現在のブランチの先端を指していないため、ブランチ名の代わりにSHA-1 :

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

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


切り離されたヘッドから回復する方法に関するいくつかのオプション:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

これにより、目的のコミットを指す新しいブランチがチェックアウトされます。
このコマンドは、特定のコミットにチェックアウトします。
この時点で、ブランチを作成して、この時点から作業を開始できます。

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

いつでも使用できreflogます。
git reflog 更新された変更が表示さHEADれ、目的のreflogエントリをチェックアウトすると、HEADこのコミットに戻ります。

HEADが変更されるたびに、新しいエントリが reflog

git reflog
git checkout HEAD@{...}

これにより、目的のコミットに戻ります

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


git reset --hard <commit_id>

HEADを目的のコミットに「移動」します。

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts if you've modified things which were
# changed since the commit you reset to.
  • 注:(Git 2.7以降)も使用できgit rebase --no-autostashます。

git revert <sha-1>

指定されたコミットまたはコミット範囲を「元に戻す」。
リセットコマンドは、指定されたコミットで行われた変更を「取り消し」ます。
元に戻すコミットを含む新しいコミットはコミットされますが、元のコミットも履歴に残ります。

# Add a new commit with the undo of the original one.
# The <sha-1> can be any commit(s) or commit range
git revert <sha-1>

このスキーマは、どのコマンドが何を実行するかを示しています。
ご覧のとおり、をreset && checkout変更しHEADます。

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


最新のコミットではない場合-履歴内の以前のコミットが別のブランチの先端でない限り、HEADが履歴内の以前のコミットを指していることを意味します。私の経験では、HEADが他のブランチによっても指し示されているコミットを指していなければ、あなたは切り離されていると言えます。これはタグには適用されません。
Tim

デタッチされたHEADにいることができ、同時にこのブランチのHEADと同じコミットを持つブランチがあります。コメントを理解でき
ません

3
見出しのインラインコードマークアップの使用に問題があります:)
jub0bs

それを強調するためのより良い方法を見つけることができませんでした。自由に編集してください。どういたしまして
CodeWizard

22

行う

git reset 23b6772

あなたが正しい位置にいるかどうかを確認するには:

git status

あなたは何かを見ます

ブランチマスター上ブランチは17回のコミットで 'origin / master'の背後にあり、早送りすることができます。

次に、リモートの履歴を書き換えて変更を反映します。

git push --force-with-lease // a useful command @oktober mentions in comments

1
と非常に注意してくださいgit push --force。多くの状況では、それはあなたしばらくのためのチームの少なくとも人気者....になります
ケイV

上記のメモに追加するために、私はabout.gitlab.com/blog/2014/11/26/keeping-your-code-protectedでこの引用に出くわし、「単一のgit push --forceコマンドを追加する必要がありました。多くの人にとってその日は簡単に台無しになってしまいます。[186 Jenkins]リポジトリでは、ブランチヘッドが巻き戻されて古いコミットを指すようになり、結果として、新しいコミットはgit-pushの失敗後に誤った場所に置かれました。」
ケイV

2
見てみましょう@KayV git push --force-with-lease(Thoughtbot記事:thoughtbot.com/blog/git-push-force-with-lease
oktober

1
便利なフラグ、@ oktober、そして良い記事。ここに追加していただき、ありがとうございます。
ケイV

1
ありがとうございました!これにより、不適切なマージを元に戻すことができました。マージはrevertコミットと同じように反応しないので、信じられないほど難しい状況に陥っていました。force-with-lease他の人の作業に影響を与えずにブランチのgit履歴を書き直す自信がありました。ブラボー!
anon58192932

11

可能な限り迅速な解決策(わずか1ステップ)

使用する git checkout -

あなたが表示されますSwitched to branch <branch_name>。目的のブランチであることを確認します。


簡単な説明:このコマンドはHEADを最後の位置に戻します。この回答の最後にある結果に関する注記を参照してください。


記憶法:このアプローチは、cd -以前にアクセスしたディレクトリに戻るために使用する方法とよく似ています。構文と適用可能なケースはかなり一致しています(たとえば、HEADを実際に元の場所に戻したい場合に便利です)。


より体系的な解決策(2ステップ、ただし覚えやすい)

迅速なアプローチがOPの問題を解決します。しかし、状況が少し異なる場合はどうなりますか?Bashを再起動してから、HEADが切り離されていることに気付いたとします。その場合、2つの簡単で覚えやすい手順を次に示します。

1.必要なブランチを選びます

使用する git branch -v

既存のローカルブランチのリストが表示されます。ニーズに合ったブランチ名を取得します。

2. HEADをそれに移動します

使用する git checkout <branch_name>

あなたが表示されますSwitched to branch <branch_name>。成功!


成果

どちらの方法でも、今までどおり作業の追加とコミットを続行できます。次の変更はで追跡され<branch_name>ます。

HEADがデタッチされている間に変更をコミットした場合は、git checkout -との両方にgit checkout <branch_name>追加の指示が表示されることに注意してください。


私は(8acc968はHEAD〜2であると仮定して)ない場合ので、これは動作していないgit checkout 8acc968、その後git branch -v持ってMyBranch下のリストに...しかし、その後、git checkout MyBranch私のコメントを削除します。
2018年

こんにちは@amuliar- git checkout 8acc968ブランチではなくコミットをチェックアウトします。MyBranch必要なコミットがある場合は、を試してくださいgit checkout MyBranch。コミット8acc968の変更が含まれていない場合は、ブランチをチェックアウトした後でそれらの変更をマージする必要があります。
Kay V

答えてくれてありがとう!私はgit checkout以前のコミットを見に行き、最新のコミットに戻りたいと思っていました。しかし、最新のコミットハッシュがないと、私はかなり迷っていました。このソリューションは私の状況に最適です!
zyy

4

質問は次のように読むことができます:

私はHEADat でdetached状態で23b6772、入力しましたgit reset origin/master(スカッシュしたかったため)。気が変わったのですが、どうすれば元の場所に戻ることHEADができ23b6772ますか?

簡単な答えは次のとおりです。 git reset 23b6772

しかし、この質問HEADに出くわしたのは、以前の参照を参照したいと思ったり、何らかの略記がないかどうかをグーグルで調べたりするたびに、タイプ入力(コピーと貼り付け)のコミットハッシュまたはその省略形にうんざりしたからです。

あることがわかりました!

git reset -(または私の場合git cherry-pick -

ちなみにどちらが* nixのcd -前の現在のディレクトリに戻るのと同じでした!ですから、私は1つの石で2つのことを学びました。


0

コマンドを実行するとgit checkout commit_id、HEADから切り離され13ca5593d(say commit-id)、ブランチが使用可能になります。

前の場所に戻り、コマンドを賢く実行します-

  1. git pull origin branch_name (マスターと言う)
  2. git checkout branch_name
  3. git pull origin branch_name

リモートリポジトリからコミットが更新され、以前の場所に戻ります。


0

今日、私は誤ってコミットをチェックアウトして作業を開始し、デタッチHEAD状態でいくつかのコミットを行いました。次に、次のコマンドを使用してリモートブランチにプッシュしました。

git push origin HEAD: <My-remote-branch>

その後

git checkout <My-remote-branch>

その後

git pull

最終的に、detach HEADで行ったすべての変更をブランチで取得しました。


0

これは技術的な解決策ではないかもしれませんが、機能します。(チームメイトの誰かがローカルに同じブランチを持っている場合)

ブランチ名をbranch-xxxと仮定します。

解決する手順:

  • 更新やプルを行わない-何も
  • 彼のマシンでbranch-xxxから新しいブランチ(branch-yyy)を作成するだけです
  • 以上で、既存の変更はすべてこの新しいブランチ(branch-yyy)に含まれるようになります。このブランチで作業を続けることができます。

注:これも技術的な解決策ではありませんが、確実に役立ちます。

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