web-dev-qa-db-ja.com

マージ後のGitスカッシュ履歴

大規模なプロジェクトの上流をローカルのgitリポジトリにマージしました。マージ前は、読みやすい少量の履歴がありましたが、マージ後は、現在、大量の履歴がリポジトリにあります。アップストリームリポジトリからのすべての履歴コミットは必要ありません。

このアップストリームマージの後に、私が保持したい他のコミットがありました。アップストリームマージ後に行われたコミットを維持しながら、アップストリームからマージされたすべての履歴を1つのコミットに押しつぶすにはどうすればよいですか?

16
E-rich

私が使用することになった解決策は、手動で履歴を再作成することでした。これを行ったのは、主に、エレガントなソリューションを探すのにあまり時間をかけたくなく、それほど多くの履歴がなかったためです(手動でマージする必要がある約30のコミット)。

そのため、巨大なアップストリームをマージする前にブランチを作成しました。

git checkout -b remove-history-fix <commit ID before merge>

次に、--squashオプションを使用してアップストリームを再マージしました。

git merge --squash <upstream tag>

次に、古いブランチ(アップストリームの履歴が大量にあるブランチ)からマージした後、コミットを手動で選択しました。

git cherry-pick <commit ID>

これらすべてのコミットが私のremove-history-fixブランチにマージされた後、アップストリーム履歴を持つブランチを削除しました。

git branch -D <upstream-history-branch>
11
E-rich

ここにある戦略を使用して、マスターブランチから複数のマージを行った後、いくつかのコミットを潰すことができました: https://stackoverflow.com/a/17141512/1388104

git checkout my-branch            # The branch you want to squash
git branch -m my-branch-old       # Change the name to something old
git checkout master               # Checkout the master branch
git checkout -b my-branch         # Create a new branch
git merge --squash my-branch-old  # Get all the changes from your old branch
git commit                        # Create one new commit

押しつぶされたブランチを以前にプッシュしたリモートリポジトリにプッシュする必要がある場合は、強制的に更新する必要があります。 git Push Origin my-branch -f

7

あなたのためのいくつかのオプション:

ロギングを制限する

正確にはあなたが求めていたものではありませんが、おそらく良い代替手段であり、はるかに簡単です。これにより、通常のようにgitを使用できますが、表示したくないものはすべて非表示になります(問題が、生のストレージスペースではなく、ログを乱雑にする履歴であると想定しています。ブランチでマージを潰すことはできないと思います。そもそもマージアクションのためにアップストリームをフェッチした場合、gitがアップストリームからのすべてのコミットを含めないようにします。).

この場合、通常のマージを実行しますが、ログを記録するときに、コマンドに--first-parentを追加します。

たとえば、私が持っているかもしれないオプションがなければ(「もっとサンプルする」1から3は実際にはもっとたくさんのコミットだったと仮定します)

$ git log --oneline
0e151bf Merge remote-tracking branch 'Origin/master' into nosquash
f578cbb sample more 3
7bc88cf sample more 2
682b412 sample more 1
fc6e1b3 Merge remote-tracking branch 'Origin/master'
29ed293 More stuff
9577f30 my local change
018cb03 Another commit
a5166b1 Initial

しかし、--first-parentを追加すると、次のようにクリーンアップされます。

$ git log --oneline --first-parent
0e151bf Merge remote-tracking branch 'Origin/master'
fc6e1b3 Merge remote-tracking branch 'Origin/master'
9577f30 my local change
018cb03 Another commit
a5166b1 Initial

分岐した後のマスターからのすべてのコミット(「ローカル変更」は発散コミット)がなくなっていることに注意してください。マージしたときも含めて、作成したコミットのみが表示されます。マージ中にもっと適切なコミットメッセージを使用した場合は、変更のバッチが何であったかさえ知っているかもしれません。

履歴を置き換える

これはあなたが尋ねたことのためです。

https://git-scm.com/book/en/v2/Git-Tools-Replace からインスピレーションを得ています

ここで行うことは、リモートの履歴を押しつぶし、それらの履歴を私たちの観点から押しつぶされたバージョンに置き換え、押しつぶされたバージョンをマージすることです。

私のサンプルリポジトリでは、アップストリームが追加した、まだマージしていないリビジョンは、Origin/master(f578cbb "sample more 3")に682b412 "sample more 1"でした(この例ではそれほど長くはありませんが、50のコミットがあると仮定します)またはその間の何でも)。

私が最初に欲しいのは、リモート側のローカルブランチです。

git checkout -b squashing Origin/master

次に、早く潰したい

git reset --soft 682b412~
git commit -m "Squashed upstream"

チルダ~文字に注意してください。これにより、ブランチは押しつぶしたい範囲の最初のコミットの親になり、--softを指定したため、インデックスはまだ押しつぶしたい範囲の最後のコミットにあります。コミット行は、最初から最後までの内容で構成される単一のコミットになります。

この時点で、オリジン/マスターブランチとスカッシングブランチのツリーコンテンツは同じですが、履歴が異なります。

ここで、Origin/masterの元のコミットへの参照を確認したら、代わりに押しつぶされたコミットを使用するようにgitに指示します。 git logを使用すると、新しい「Squashedupstream」コミットが1f0bc14であることがわかります。

git replace f578cbb 1f0bc14

これ以降、gitは「squashedupstream」コミットを使用します。

元のブランチに戻ります(「マスター」の場合)

git checkout master
git merge f578cbb

これは、オリジンマスター(f578cbb)をマージしているように見え、実際には1f0bc14のコンテンツを取得しますが、f578cbbの親SHA1を持つものとしてログに記録します。

押しつぶすブランチはもう必要ないので、取り除くことができます。

ここで、アップストリームがさらに機能を追加したとしましょう。この簡単な例では、アップストリームのリポジトリで、ログに次のように表示される場合があります。

84f5044 new feature
f578cbb sample more 3
7bc88cf sample more 2
682b412 sample more 1
29ed293 More stuff
018cb03 Another commit
a5166b1 Initia

ただし、アップストリームをフェッチした後、リポジトリからログを見ると、代わりに次のように表示されます。

84f5044 new feature
f578cbb squashed upstream
29ed293 More stuff
018cb03 Another commit
a5166b1 Initial

私たちにも履歴が押しつぶされているように見えることに注意してください。さらに重要なことに、押しつぶされたアップストリームSHA1は、アップストリームの履歴で使用されているものを示しています(彼らにとっては実際には「samplemore3」コミットです)。

したがって、マージは通常どおり機能し続けます

git merge Origin/master

しかし、そのような雑然としたログはありません。

4a9b5b7 Merge remote-tracking branch 'Origin/master' for new feature
46843b5 Merge remote-tracking branch 'Origin/master'
84f5044 new feature
f578cbb squashed upstream
fc6e1b3 Merge remote-tracking branch 'Origin/master'
29ed293 More stuff
9577f30 my local change
018cb03 Another commit
a5166b1 Initial

アップストリームでの「新機能」のコミットが同様に多数のコミットである場合、このプロセスを繰り返してそれを押しつぶすことができます。

2
John O'M.

そのリモートリポジトリまたは同じプロジェクトの他のリポジトリとプッシュバックまたは再度マージすることはできないため、これを行う方法はありません。押しつぶすと、履歴が変更され、リポジトリとリモートリポジトリ間で異なるsha1ハッシュが発生します。

あなたは大きな歴史と共に生きなければならないでしょう。

1
Femaref