2012-01-30 5 views
1

Gitブランチを特定のコミットにロールバックしたい。そこで私はgit logを実行し、コミットSHAハッシュを見つけ、git checkout <myhash>を実行します。Gitブランチの特定の時点(つまりコミット)にどのようにチェックアウトするのですか?

これは通常正常に動作しますが、今回は何かが怪しいです。 git logをもう一度見ても、最新のコミットが正しいことがわかりますが、私はさらに多くのコミットを見逃しています。私の上には、このコミットがあります。このコミットは別のブランチ(another)からのマージの一部であり、そのブランチからの履歴、つまり事前マージが表示されます。

master's log, pre-merge:  D-C-----B'-B-A-----F 
another's log:    7-6-----5-4--------3-2-F 
master's log, post-merge: M-7-6-D-C-5-4-B'-B-A-3-2-F 

私は5をコミットし、anotherからの歴史の中でコミットを取得チェックアウト:

5-4-3-2-F 

しかし、私は、masterからの歴史の中でコミットを好きポストマージしたい:

5-4-B'-B-A-3-2-F 

a repo私はこれをテストできます:

$ git clone git://github.com/henrik242/Git-Branch-Test.git 
$ cd Git-Branch-Test 
$ git checkout -t origin/another 
$ git log ## The commits are named "test [2-7]" 
$ git checkout master 
$ git log ## master's original commits are named "test [A-D]". 
$ git checkout 68c1226a0c ## test 5 
$ git log ## We now have the commits in the history from the "another" branch, 
      ## even though this commit exists in the "master" branch as well 

私はほとんど私がやりたいgit rebase -iを使用することができます。

$ git branch back-in-time 
$ git checkout back-in-time 
$ git rebase -i 18b1a648bc ## the SHA1 of 'test 4', the commit before 'test 5' 

エディタが起動します:不要なコミットを削除します。保存して終了、およびgit logは今、希望コミットを示しています

5-4-B'-B-A-3-2-F 

問題はgit rebase -iは難しい右のコミットを選択することができた、git logと同じ順序でコミットを示していないということです。

+4

次の2つのコミットをしてい'2'というラベルのコミット・グラフでは、同じハッシュを持つことはできず、コミット・グラフの別の場所にあることもできません。彼らが実際に同じコミットかどうかを明確にすることができますか? –

+1

あなたはまた、祖先を右に、子孫を右に持つことになっている従来の方法(例えば、Gitのマンページ)からあなたの写真をミラーリングしました。 – Cascabel

+0

@MarkLongair:2,3,4,5,6の2つはすべて同じですが(私はそうは思いませんが)、1の2つのラベルは間違いなく同じです! OPに:マークのコメントと一緒に、コミット2をどのようにチェックアウトしましたか? SHA1で?異なるコミットのSHA1は、定義が異なります。 – Cascabel

答えて

0

私は自分の質問に答えます:このワークフローが機能するように(そして何らかの意味合いを持たせるために)、私はgitログのトポロジカルな順序を使用する必要があります:git log --topo-order。ログは次のようになり、この方法:それは同様トポロジカル順序でだから

master's log, pre-merge:    D-C-B'-B-A-F 
another's log:    7-6-5-4-3-2------------F 
master's log, post-merge: M-7-6-5-4-3-2-D-C-B'-B-A-F 

は今git rebase -iでの順序は、理にかなっています。あなたが問題のコミットに達するまで、ちょうど下のコミットをスニップして保存してください!

(私はバグを導入したコミット突き止めるしようとしたので、注意点として、私は最初の場所でこのワークフローを必要としていました。その後、私はgit bisectが私よりも、この上の優れた仕事をしていません実現。)

0

私は十分な時間を言うことはできません:あなたが求めている歴史は決して存在しませんでした。手動で作成する場合は、チェックアウトするようなものはまったくありません。どのような方法でマージしても、何らかの融合された歴史にコミットすることはありません。あなたの質問が「このような履歴を手動で作成するにはどうすればよいのですか?しかし、あなたは既にリベースを使う方法を知っているようです。

あなたの主な誤解は、git-logの出力である可能性があります。注文コミットはgit logによって表示され、基本的に任意の選択です。歴史は線形ではありませんが、それを一つずつリストアップする必要があります。その順序は、1つのコミットが前のものの親であることを意味するわけではないので、それらのコミットの1つをチェックアウトすると、その下に印刷されたすべてのものが結合されます。あなたの質問に書いたように、コミットのリストを出力するかもしれませんが、あなたのサンプルリポジトリではこれは履歴のようです。 gitk --allまたはgit log --graphと表示されます。

1 - 2 - 3 - 4 - 5 - 6 - 7 (another-branch) 
\      \ 
    A - B - C - D - --------M (master) 

これだけです。マージはそれらのブランチを魔法のようにマッシュしません。それはマージされたコミットを作成します。その親はマージされたコミットであり、マージされたコミットの内容の組み合わせを含みます。したがって、コミット2をチェックアウトすることも、コミットBをコミットすることもできますが、 "マスターブランチにコミット2"はありません。あなたが好きなのであれば、コミットBをチェックしてコミット2をマージし、あなたが得るものを見ることができます。

私が言うことができる限り、あなたが望むと言っているコミットのリストは、コミット5とBをマージし、それを任意の方法でフラット化することによって得られるものです。あなただけのマージの結果をしたい場合:

git checkout -b foo <commit-5> 
git merge <commit-B> 

は、あなたが実際に平らな歴史をそのようにしたい場合:

git checkout -b foo <commit-5> 
git rebase -i <commit-B> 
# reorder them however it is you wanted them 

しかし、これらは、すべてのユーザーの決定です。存在しなかったリポジトリの状態を作成しています。それは決して存在しなかったので、それを作成する必要があります。


コメントのハッシュについては、SHA1がコミットを一意に識別します。コミット2のSHA1は、そのコミットのみのSHA1です。あなたはあなたのテストレポで私が間違っていることを証明していない、あなたは私が正しいことを証明した。そこにはコミットが1つしかなく、ハッシュが1つしかない。

コミットは、メタデータ(作成者/コミッター名、電子メール、日付、コミットメッセージ)、その親への参照、それが表すツリー(スナップショットと考える)コンテンツの)。コミット2はその特定のスナップショットを表します。それ以上のものはありません。その親はコミット1です。これはタイムスタンプの問題ではありません。コミットはSHA1によってその親を知っています。コミット2の親はコミット1です。マスタブランチや別のブランチから到達するかどうかにかかわらず、コミット2は1つしかありません。画像を見ると、7,6,5,4,3を介してマスタブランチにどのようになっているかを確認できます。

+0

これは結構ですが、元の質問に戻ります:ブランチ上の特定の時点に「ログを巻き戻す」ことは可能ですか?あるいはチェリーで履歴を作り直す必要がありますか?すべてのコミットを新しいブランチに入れますか? – neu242

+0

私は考えていない*再作成しようとしている時点を教えてください。存在していたコミットのどれかをチェックアウトすることができます。あなたは決して存在しなかったものをチェックアウトすることはできません。あなたが望むものがA、B、Cと2、3、4を持っていてDか5,6,7のものでなければ、それはその歴史に存在するものではありません。あなたはCで新しいブランチをチェックアウトし、4をマージすることでそれを作成することができました。しかし、あなたのリポジトリは決してそうではありませんでした。 – Cascabel

+0

私は物事をより明確にするために投稿を編集しました。私はgitログの私のASCIIアートが実際のブランチによく似ていると思う。 – neu242

1

Mergeはコミットを混ぜ合わせるものではなく、@ Jefromiの答えに示されているようにブランチに加わるだけです。だからもちろん、いつでもツリーの状態を復元することができますが、マージ前の時間になったら、正しいブランチを選ぶように注意する必要があります。だから、git log --oneline --graphを使うべきだと思うので、与えられた時にそれぞれのブランチで最新のコミットを選ぶことができます。そのコミットをチェックすると、明らかにそのブランチのコミット履歴のみがその時点で保持されます。

実際に両方のブランチからのコミットを混在させたい場合は、git cherry-pickまたはgit rebase -iを使用するワークフローが、両方のブランチからコミットを時系列的にまっすぐなブランチに順序付ける必要があります。これはすべての種類の問題を必要とします。少なくとも、多くのマージ競合があります。また、中間状態は意味的に矛盾している可能性が最も高い。

関連する問題