私は最近このトピックについてブログを書きました:
この機能ブランチを最新の状態に保つにはどうすればよいですか?最新のアップストリームコミットのマージは簡単ですが、アップストリームにプッシュされたときに評価されないため、マージコミットの作成は避けたいと考えています。アップストリームの変更を効果的に再コミットすると、それらのアップストリームコミットは新しいハッシュを取得します(彼らは新しい親を取得するので)。これらのマージされたコミットは、それらの更新を個人のGitHub機能ブランチにプッシュするときにGitHubプルリクエストに反映されるため、これは特に重要です(プルリクエストを発行した後に行った場合でも)。
そのため、マージする代わりにリベースする必要があります。
git co devel #devel is ansible's HEAD aka "master" branch
git pull --rebase upstream devel
git co user-non-unique
git rebase devel
rebaseオプションとgitへのrebaseコマンドはどちらもツリーをクリーンに保ち、マージコミットを回避します。ただし、これらはリベースされている最初のコミット(最初のプルリクエストを発行したもの)であり、リモートgithubリポジトリブランチに残っている元のハッシュとは異なる新しいコミットハッシュがあることに注意してください。
両方のブランチが異なるため、これらの更新を個人のGitHub機能ブランチにプッシュすると失敗します。ローカルブランチツリーとリモートブランチツリーは、コミットハッシュが異なるため、「同期がとれていません」。Gitは、最初git pull --rebase
にプッシュしてからもう一度プッシュするように指示しますが、履歴が書き換えられたため、これは単純な早送りプッシュではありません。それをしないでください!
ここでの問題は、最初に変更されたコミットを元の状態で再度フェッチし、それらがローカルブランチの上にマージされることです。非同期状態のため、このプルは正しく適用されません。コミットが2回表示されるという壊れた履歴が表示されます。これらすべてをGitHub機能ブランチにプッシュすると、これらの変更は元のプルリクエストに反映され、非常に醜くなります。
AFAIK、これに対する完全にクリーンな解決策は実際にはありません。私が見つけた最善の解決策は、ローカルブランチをGitHubブランチに強制的にプッシュすることです(実際には、早送りではない更新を強制します)。
git-push(1)によると:
Update the origin repository’s remote branch with local branch, allowing non-fast-forward updates. This can leave unreferenced commits dangling in the origin repository.
したがって、引っ張らないで、次のように強制的に押してください。
git push svg +user-non-unique
または:
git push svg user-non-unique --force
これにより、実際にはリモートブランチが、ローカルブランチ内のすべてのもので明らかに上書きされます。リモートストリームにある(そして失敗を引き起こした)コミットはそこに残りますが、ぶら下がっているコミットになり、最終的にgit-gc(1)によって削除されます。大きな問題ではない。
私が言ったように、これはAFAICSの最もクリーンなソリューションです。これの欠点は、PRがそれらの最新のコミットで更新されることです。これは後日取得され、PRのコメント履歴に同期していないように見える可能性があります。大きな問題はありませんが、混乱を招く可能性があります。