34

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

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

4

4 に答える 4

12

私が使用することになった解決策は、履歴を手動で再作成することでした。これを行った主な理由は、エレガントなソリューションを探すのにあまり時間をかけたくなく、それほど多くの履歴がなかったためです(手動でマージする必要がある約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>
于 2012-12-28T13:38:24.440 に答える
2

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

ロギングの制限

あなたが求めたものとは正確には異なりますが、おそらく良い代替手段であり、はるかに簡単です。これにより、通常のように 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 ブランチと squashing ブランチのツリー コンテンツは同じですが、履歴は異なります。

ここで、origin/master の元のコミットへの参照を見つけたら、代わりに押しつぶされたコミットを使用するように git に指示します。を使用するgit logと、新しい「押しつぶされたアップストリーム」コミットが 1f0bc14 であることがわかるので、次のようにします。

git replace f578cbb 1f0bc14

これ以降、git は「押しつぶされたアップストリーム」コミットを使用します。

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

git checkout master
git merge f578cbb

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

squashing ブランチはもう必要ないので、削除できます。

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

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 は、アップストリームの履歴で使用されているものを示しています (実際には、「さらに 3 回のサンプル」コミットです)。

そのため、マージは通常どおり機能し続けます

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

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

于 2015-06-28T05:42:43.163 に答える
0

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

大きな歴史とともに生きていかなければなりません。

于 2012-12-26T17:34:22.183 に答える