48

を使用してマージの競合が発生した場合、ファイルの違いだけでなく、コミットの観点からgit rebase競合の原因を特定するにはどうすればよいですか?

私はすでに(基本的な)使用方法git mergetoolまたはgit addそれ以前の方法を知っていgit rebase --continueますが、ファイル間の違いだけでは不十分な場合があります。作業ツリーに適用できなかったコミットのログと差分を確認したいのです。

git log --mergeを使用している場合に親がコミットすることを示す他の質問を読みましたgit merge。とにかく衝突に遭遇して言われたときに試してみましたfatal: --merge without MERGE_HEAD?

問題のあるコミットを特定するにはどうすればよいですか?

4

8 に答える 8

41

短い答え

それが言うなら

Patch failed at 0001 commit message for F

次に実行します

$ head -1 .git/rebase-apply/0001
From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001

ad1c77失敗したコミットのSHAを取得し、それを確認するために使用git show ad1c77します。

長い答え

このツリーから始めましょう:

A---B---C---D
     \
      E---F---G

$ git checkout G
$ git rebase D

リベースの競合が発生すると、それは

  • C--D共通の祖先からのアップストリームの変更( )( B)に加えて、すでにリベースされた変更とすでに解決された競合(E'
  • 次のコミットのパッチ(F

しばらく様子を見てみましょう:

1) A---B---C---D---E'          <- E patched and committed successfully as E'
2) A---B---C---D---E'---       <- failed to patch F onto E'

エラーメッセージは次のとおりです。

First, rewinding head to replay your work on top of it...
Applying: commit message for F
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging 1.txt
CONFLICT (content): Merge conflict in 1.txt
Failed to merge in the changes.
Patch failed at 0001 commit message for F

Fまず、コミットメッセージが表示されるため、それがであったことがわかります。ただし、コミットメッセージがすべて「foo」、「documentation」、または「somefixes」のように見える場合、これは役に立ちません。SHAIDad1c77またはパッチの内容が本当に必要です。

の本当のアイデンティティを見つける方法は次のFとおりです。

リベースの競合がリストされている場合、次のように表示されます。

Patch failed at 0001 commit message for F

次に.git/rebase-apply/、パッチファイルがある場所を調べます0001

$ ls .git/rebase-apply
0001          head-name     msg           orig-head     sign
0002          info          msg-clean     patch         threeway
apply-opt     keep          next          quiet         utf8
final-commit  last          onto          rebasing

パッチファイルには、元のcommit-idが含まれています

$ head -1 .git/rebase-apply/0001
From ad1c7739c1152502229e3f2ab759ec5323988326 Mon Sep 17 00:00:00 2001

その後、それを見ることができます。

もっと簡単な方法があるはずですが、これはうまくいきます。

パッチが失敗したという事実は、別のコミットが原因である可能性があることに注意してください(共通の祖先HEADとリベースターゲットにリベースしている場合)。そのコミットを見つけることはかなり複雑ですが、逆にリベースを実行して見つけることができます。

$ git checkout D
$ git rebase G
于 2010-01-22T15:54:00.473 に答える
11

競合の解決を停止している間git rebase、次のコマンドは競合するコミット(競合するファイルだけでなくすべて)を表示します。つまり、現在どこにいるかに関係なく、コミットは新しいベースで再生/リベースされています。に:

git show $(< .git/rebase-apply/original-commit)

特定の競合するファイル(解決しようとしているファイル)の競合のみを表示する場合は、次のようにします。

git show $(< .git/rebase-apply/original-commit) -- /path/to/conflicting/file

この答えの作成で虐待された猫はいません:)。

于 2017-01-18T03:21:35.617 に答える
9

現在の/失敗したコミットを表示する

これは新しい機能かもしれませんが、REBASE_HEAD現在停止している場所でコミットを提供します(たとえば、コミットが適用に失敗した場合)。コミットを完全に確認したい場合は、次を使用できます

git show REBASE_HEAD

より詳細な代替手段として、を使用できますgit rebase --show-commit-patch。ドキュメントはそれらが同等であると言います。

仕事を始めてから何が変わったかを示す

リベース元とリベース先の間で何が変更されたかを確認したい場合は、2つのブランチ間の差分を取得できます。たとえば、からリベースする場合は、masterorigin/masterを使用できます。

git diff master..origin/master

または、個々のコミットとして変更を確認したい場合:

git log -p master..origin/master

ハッシュを使用したい場合、またはしばらくしてリベースに戻ってきて、リベースしているブランチを思い出せない場合はgit status、2つのブランチを表示するために使用できます。例えば:

現在、ブランチ「master」を「b5284275」にリベースしています

次に、何が変更されたかを確認するには、次を使用できます。

git diff master..b5284275
于 2018-10-03T16:46:19.823 に答える
6

Git 2.17(2018年3月)以降、を使用する必要はありませんrebase-apply

新しい「--show-current-patch」オプションは、 「 」(および「」)が競合で停止したdiffときに適用されるようにするためのエンドユーザー向けの方法を提供します。git rebasegit am

NguyễnTháiNgọcDuy ()によるcommit fbd7a23commit 6633529commit 984913a(2018年2月11日)参照してください。濱野純雄による合併---コミット9ca488c2018年3月6日pclouds
gitster

am:-show-current-patchを追加します

サインオフ:NguyễnTháiNgọcDuy

ユーザーを指差すと$GIT_DIR/rebase-apply、そこをいじくり回すように促される可能性がありますが、これは良いことではありません。

これにより、ユーザーはパッチを確認する必要があるときに、パスをどこかに保持する必要がなくなります(2、3のコマンドの後、パスがスクロールバックバッファーから外れる可能性があるため)。

詳細については、「現在のgitインタラクティブリベース操作を表示する」を参照してください。

例:

C:\Users\VonC\repo\src>git rebase origin/master
First, rewinding head to replay your work on top of it...
Applying: change code
Using index info to reconstruct a base tree...
M       a/src/file
Falling back to patching base and 3-way merge...
Auto-merging a/src/file
CONFLICT (content): Merge conflict in a/src/file
error: Failed to merge in the changes.
hint: Use 'git am --show-current-patch' to see the failed patch                  <======
Patch failed at 0001 change code
Resolve all conflicts manually, mark them as resolved with
"git add/rm <conflicted_files>", then run "git rebase --continue".
You can instead skip this commit: run "git rebase --skip".
To abort and get back to the state before "git rebase", run "git rebase --abort".

次に、次のようになります。

C:\Users\VonC\rep\src>git am --show-current-patch
  commit xxx (master)
  Author: VonC <vonc@vonc.com>
  Date:   Mon Nov 4 13:59:18 2019 +0100

      change code

  diff --git a/a/src/file b/a/src/file
  index yyy..zzz 100644
  --- a/a/src/file
  +++ b/a/src/file
  @@ -13,5 +13,5 @@ file: /a/src
   content line 1
   content line 2
   content line 3
   content line 4
  -content line 5
  -content line 6
  +content bis line 5
  +content bis line 6

" git am --short-current-patch"は、停止したステップの電子メールを表示する方法であり、 ""を直接フィードするのには適していませんgit apply(適切な ""入力になるように設計されていgit amます)。

Git 2.26(2020年第1四半期)では、パッチ部分のみを表示する新しいオプションを学習しました。

Paolo Bonzini()によるcommit aa416b2commit f3b4822commit e8ef1e8commit bc8620bcommit 62e7a6f(2020年2月20日)を参照してください。濱野純雄による合併---コミット0e0d7172020年3月9日bonzini
gitster

am:.git / rebase-apply/patchを取得するための--show-current-patch=diffのサポート

報告者:J。ブルースフィールズ
署名者:パオロボンジーニ

" "がコミット984913a210git am --show-current-patchに追加されたとき( " :add --show-current-patch"、2018-02-12、Git v2.17.0-rc0 --mergeバッチ#7にリストされています)、" "はそれをの代替。amgit am.git/rebase-merge/patch

残念ながら、提案はやや見当違いです。たとえば、「」の出力は、quoted-printableまたはbase64としてエンコードされている場合、git am --show-current-patch「」に渡すことはできません。git apply

git am --show-current-patch提案をまっすぐにするために、「」に新しいモードを追加します。

新しいモードは次のdiffとおりです。

--show-current-patch[=(diff|raw)]

git am競合が原因で停止したメッセージを表示します。
が指定されている場合raw、電子メールメッセージの生の内容を表示します。の場合diff、差分部分のみを表示します。
デフォルトはraw

と:

am--show-current-patch=raw:の同義語としてのサポート--show-current-patch

サインオフ:Paolo Bonzini

ワークツリーの操作を簡素化し、ユーザーがに突っ込むのを避けるために、「」がstdoutにコピーするモードも提供する.git方がよいでしょう。git am.git/rebase-merge/patch

1つの可能性は、完全に別個のオプションを持ち、たとえば--show-current-message(for .git/rebase-apply/NNNN)と--show-current-diff(for )を導入する.git/rebase-apply/patch一方で、-show-current-patchを非推奨にすることです。

これにより、シリーズの最初の2つのパッチが不要になります。ただし、長い共通プレフィックスでは、「」などの省略形オプションを使用できませんでした--show

したがって、代わりに文字列引数をに追加することにしました--show-current-patch

于 2019-11-04T17:11:18.310 に答える
2
cat .git/rebase-apply/original-commit

これを考えると:

A---B---C---D
     \
      E---F---G

$ git checkout G
$ git rebase D

Fを適用しようとしているマージの競合があるとすると:

A---B---C---D--E'--!
     \
      E---F---G

次に、original-commitファイルにFのハッシュが表示されます。これは「彼らの」バージョンです。

また、この場合、HEAD(.git / HEAD)はE'になります。これは「私の」バージョンです。HEAD^は「ベース」バージョンになります。

これは、少なくともgit1.7.9に当てはまります。

于 2014-09-03T12:04:52.890 に答える
2

なぜ私が.git/rebase-apply自分の状況にいないのかわからない。同じ状況にある人のために、これが私のバリエーションです。

git show $(cat .git/rebase-merge/stopped-sha)

またはエイリアスとして...

git config --global alias.sp='!git show $(cat .git/rebase-merge/stopped-sha)'
于 2014-12-25T00:31:21.960 に答える
1

競合が発生したときに適用されていたコミットを確認するには、...を使用します。

git am --show-current-patch
于 2019-12-17T20:35:23.083 に答える
0

多くの場合、リベースの最中にあり、不要なコミットをスキップしたいと思うでしょう。

残念ながら、git statusコミットの最中であることを示し、git rebase --continue git rebase --skipまたはを使用することをお勧めしgit rebase --abortますが、現在どのコミットを行っているかはわかりません。

そのため、すべきgit rebase --skipかどうかを判断するのは難しい場合があります。

ただし、次のコマンドを実行して、実行中のコミットを確認する方法はまだあります。

git log -1 $(< .git/rebase-apply/original-commit)
于 2018-05-28T01:46:55.750 に答える