24

質問

次のようなコミットがあるとします。

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

最初の親だけに従って、完全に線形の履歴を取得するにはどうすればよいですか?

例えば、私は取得したい:

A - B - C - D - G'- H'

上記のように、G と H の sha1 が変更されることが予想されます。(明らかな理由で)。A、B、C、および D の sha1 も変化する場合、その理由を知りたいです。

バックグラウンド

これは、単純な git rebase -i を実行したときに発生する可能性のあるマージ コミットを回避することを目的としています。

本当のポイントは、たとえば、次のグラフがある場合、特定のブランチにあるコミットを判断するために追加の洞察を得ることです。

I - J - K - L - M
 \     /   /   / 
  - N - O - P -

N は K にマージされましたが、O は --strategy=ours で L にマージされ、P は M にマージされました。

このような問題のあるコミットを特定して検査できるように、履歴を線形化できるようにしたいと考えています。git cherry を使用して、N と P が上流のブランチから欠落している可能性があることを潜在的に識別したとしても、O が上流のブランチに配置されなかったことを識別できるツリーが必要ですが、ここでの提案をいただければ幸いです。 .

4

2 に答える 2

20

あなたが言ったように、次のコマンドが機能します:

git filter-branch --parent-filter 'cut -f 2,3 -d " "'

なんで?

あなたが提起した問題は、各マージ コミットを単純なコミットに変換することで解決されます。これにより、マージされた機能ブランチが孤立するため、マージされた機能ブランチが単純に削除されます。

各コミットには、1 つ以上の親コミットがあります。マージコミットは、複数取得するものです。Git はこれを履歴の各コミット オブジェクトに保存します。

このgit filter-branchコマンドは、--parent-filterオプションを使用して、すべてのコミットの親を書き換え、フィルターに として渡し、親-p SHA1が複数ある場合は繰り返すことができます。私たちのフィルターは親をカットし、すべてのコミットが単一の親を持つように強制します。

おまけとして、新しいコミットを再作成することにより、正確なコミットで手動で行う方法を次に示します。

  • コミット ツリーと最初の親を取得する

    tree=`git show -s --format=%T SHA1`
    parent=`git show -s --format=%P SHA1 | cut -d " " -f1`
    
  • 同じツリー、同じメッセージで新しいコミットを作成し、最初の親のみを祖先として保持します

    git show -s --format=%B SHA1 | git commit-tree $tree -p $parent
    
于 2013-08-01T12:48:07.210 に答える
5

次のように手動で実行します。

git rebase -i D-sha1

ファイルを編集して、G を「編集」に設定します。H の「選択」を保持します。保存してエディターを閉じます。

Git で G コミットを編集できるようになったので、F コミットのスカッシュ マージに変更してみましょう。あなたはしたい:

#cancel the merge commit and position HEAD to D
git reset --hard HEAD~
#squash merge and continue
git merge --squash F-sha1
git rebase --continue

最初のマージで必要な場合は、同じ競合を解決する必要があることに注意してください...

あなたが言うように、G と H には新しい SHA1 しかありません。

于 2013-08-01T08:05:32.327 に答える