1. ホーム
  2. git

[解決済み] git が名前の変更を検出できない

2023-06-25 22:57:44

質問

一つの枝( refactoringBranch ) には、完全なディレクトリの再構築がありました。ファイルは無秩序に移動されましたが、コンテンツは保存されました。

マージしようとした git merge --no-ff -Xrename-threshold=15 -Xpatience -Xignore-space-change refactoringBranch

git statusでは、約半分のファイルがリネーム認識されています。しかし、プロジェクト内の1万ファイルのうち、半分は移動したと認識されませんでした。

一例を挙げると、以下のようになります。

# On branch master
# Changes to be committed:

#   deleted:    404.php
#   new file:   public_html/404.php
    ...
#   deleted:    AnotherFile.php
#   new file:   public_html/AnotherFile.php
    ...
#   renamed:    contracts/css/view.css -> public_html/contracts/css/view.css

提案ですか?


先史時代

リファクタリングはgitの外部で行いました。以下のようにしました。

  1. を作成しました。 refactoringBranch に由来する master .
  2. 変更した構造を refactoringBranch の中にある変更された構造を削除しました。つまり、私の変更は他のディレクトリにあり、それを私の git リポジトリにコピーペーストしただけです。
  3. すべてを追加してコミットし、それからマージを試みました。

これが私のワークフローでした。

git checkout -b refactoringBranch
cp -R other/place/* ./
git add . -A
git commit -a -m "blabla"
git checkout master
git merge --no-ff -Xrename-threshold=15 -Xpatience -Xignore-space-change refactoringBranch

この問題は git add . -A のステップで発生します。 なぜなら、もしリネーム検出がそこで正しく行われたなら、私はマージが完璧に行われると思うからです。

どのように解決するのですか?

リネーム検出を行います。

私の最善の推測は、非常に多くの候補があるため、リネーム検出に失敗しているということです。git ソース コードは少しわかりにくいところがありますが、リネーム検出アルゴリズムの特定の検索ステップで使用される、ハードコードされた制限があるようです ( diffcore-rename.c を参照)、また、検索するペアの最大数に関する設定可能な制限もあります (設定キー diff.renameLimitmerge.renameLimit ). このため、設定可能なリミットを適切に高く設定していても、検出が失敗している可能性があります。設定可能なリミット自体は、範囲 [1, 32767] にクランプされます。

おそらく、最初に再構築のステップを実行することでこれを回避することができます。新しいレイアウトに合わせて、内容を変更せずに git mv でファイルを移動し、新しいブランチにそれをコミットして、最終バージョンに置き換えるのです。内容の変更を伴わないリネーム の方がより確実に検出されるかもしれません。これは、行った再構築がかなり単純である場合にのみ実用的であり、リネーム検出の失敗を解決できるかどうかはわかりません。

あるいは、変更を単純なファイルのグループ化で別々のコミットに分割し、各コミットでリネーム検出の候補がより少なくなるようにすることができます。

マージします。

残念ながら、新しいブランチを master の上に置くことで、git にマージに関する誤った情報を与えてしまっています。リネームが正しく検出されたかどうかに関係なく、新しく作成されたブランチを master にマージすると、master のすべてを上書きしてしまいます。