14

Github が自動的にマージできないというプル リクエストがあります。この変更は master のいくつかのコミットより遅れていますが、競合はありません。

手動でマージしても競合は発生せず、次の出力が得られます。

(on master)
$git merge otherbranch
[vim pops up for commit message, :wq]
Auto-merging <file>
Merge made by the 'recursive' strategy.
<file> | 1 +
1 file changed, 1 insertion(+)

それが Github が自動的にマージできない理由ですか? とにかく、コマンドラインから自動的にマージされました。これはGithubにとって十分に自動化されていませんか?

4

3 に答える 3

13

その理由は、git mergeデフォルトで「再帰的」マージと呼ばれる戦略を使用するためです。3 方向のマージを実行できます。一方の側からパッチを取得し、そのパッチをもう一方の側に適用して、新しいファイルを生成します。また、多くの分岐とマージが発生し、マージされる 2 つのコミットのマージ ベースが複数ある、より複雑な状況では、これを再帰的に行います。

私は最近、この同じ状況に遭遇しました:

$ git merge-base --all 90d64557 05b3dd8f
711d1ad9772e42d64e5ecd592bee95fd63590b86
f303c59666877696feef62844cfbb7960d464fc1
$

マージベースが2つあるため、3方向のマージはできません。したがって、「再帰」戦略は、最初にこれら 2 つのコミットのマージに再帰することでこれを解決しました。

$ git merge-base 711d1ad9 f303c596
3f5db59435ffa4a453e5e82348f478547440e7eb
$

OK、マージ ベースは 1 つだけなので、3 方向のマージを開始できます。両サイドの変化は?

$ git diff --stat 3f5db594 711d1ad9
 normalize/coll.py      | 116 ++++++++++++++++++++++++++++++++++++++-----------
 normalize/visitor.py   |  49 ++++++++++-----------
 tests/test_property.py |  10 +++--
 3 files changed, 120 insertions(+), 55 deletions(-)
$ git diff --stat 3f5db594 f303c596
 normalize/identity.py  | 38 +++++++++++++++++++++++++++++++-------
 tests/test_property.py |  2 ++
 2 files changed, 33 insertions(+), 7 deletions(-)
$ 

これら 2 つの diff はどちらも同じファイルに変更を加えているため、各ファイルの新しいバージョンをそれぞれの側から取得する (インデックス マージ)という単純な方法を使用して解決することはできません。代わりに、git は一方から新しいファイルを取得し、他方からパッチを適用しようとします。結果は結合されたコミットであり、次のようにシミュレートできます。

$ git checkout -b tmp
Switched to a new branch 'tmp'
$ git reset --hard f303c59666877696feef62844cfbb7960d464fc1
HEAD is now at f303c59 record_id: throw a more helpful error if record identity is not hashable
$ git merge 711d1ad9772e42d64e5ecd592bee95fd63590b86
Auto-merging tests/test_property.py
Merge made by the 'recursive' strategy.
 normalize/coll.py      | 116 ++++++++++++++++++++++++++++++++++++++-----------
 normalize/visitor.py   |  49 ++++++++++-----------
 tests/test_property.py |  10 +++--
 3 files changed, 120 insertions(+), 55 deletions(-)
$ git diff --stat 3f5db594 HEAD tests/test_property.py
 tests/test_property.py | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)
$

次に、このマージ結果を開始点として使用して、元の 3 方向マージに戻ります。これには、同じファイルへの変更も含まれます。

$ git diff --stat HEAD 90d64557| grep selector
 normalize/selector.py          |  17 +--
 tests/test_selector.py         |  19 ++--
$ git diff --stat HEAD 05b3dd8f| grep selector
 normalize/selector.py  | 29 +++++++++++++++++------------
 tests/test_selector.py |  9 +++++++++
$

ただし、ここでも変更はファイルの異なるセクションに対するものであるため、差分を取得して反対側に適用することは成功しています。

したがって、C git は、最初に 2 つの開始点の 2 つのマージ ベースで 3 方向マージを実行し、次にマージされる 2 つの元のコミットとその中間結果で別の 3 方向マージを実行することにより、このマージを解決できました。初合流。

Github の自動解決ではこれが行われません。必ずしも不可能というわけではなく、再帰的な戦略がどれだけ実装されているかはわかりませんが、注意を怠っています。これはまさに、そのような大きな緑色のボタンに期待されることです:-)。

于 2014-04-01T20:33:29.160 に答える
5

いいえ、それは合併についてではありません。リベースについてです。

ローカル リポジトリ ( forkのクローン) で、otherbranchの上にリベースしてみてくださいmaster

まず、master が元のアップストリーム リポジトリの最新のものであることを確認します。

フォーク

cd /your/local/repo
git remote add upstream /url/original/repo
git fetch upstream

# Make sure you don't have any local commmit on your master
git branch -f master upstream/master # reset your master branch 
                                     # to the one from upstream repo
git checkout otherbranch
git rebase master

そのリベースは競合を生成します。これを解決する必要がありgit addますgit rebase --continue

最後に、push --forceフォークへのブランチを作成します。これにより、プル リクエストが自動的に更新されます(他に何もする必要はありません)。

git push -u -f otherbranch origin

(すでに一度押されている場合は、 agit pushだけで十分です)

プルリクエストに関するその他のヒントについては、こちらを参照してください。

于 2013-10-17T20:29:36.900 に答える
0

デフォルトでは、マージ コミットのコミット メッセージを確認する前に、Git はブランチを自動マージできるかどうかを認識しません。

競合が発生しないことがわかっている場合は、次のようにまたはGIT_EDITORを追加するなどして、非対話型ツールに変更することで、この再帰的な自動マージのプロセスを自動化できます。cattrue

GIT_EDITOR=true git merge otherbranch

についても同じですpull-X theirsまたはのようなマージ戦略を指定することもできます-X ours

または別の方法は、リベースすることです(コマンドに追加-rしますpull)。

于 2016-07-24T13:51:34.503 に答える