Gitを使用したファイルコピー操作の記録


141

git-mvを使用してgitでファイルを移動すると、ステータスにファイルの名前が変更されたことが示され、一部を変更しても、ファイルはほぼ同じものと見なされます(これは、履歴を追跡できるので良いです) 。

ファイルをコピーすると、元のファイルに履歴があり、新しいコピーに関連付けたいと思います。

ファイルを移動してから、元の場所で再チェックアウトを試みました-一度移動したgitでは、元の場所をチェックアウトできません。

私はファイルシステムのコピーをしてからファイルを追加しようとしました-gitはそれを新しいファイルとしてリストします。

履歴を元のファイルに遡ることができるファイルの名前変更/移動を記録する方法と同様の方法で、gitにファイルのコピー操作を記録させる方法はありますか?

回答:


112

Gitは名前の変更の追跡もコピーの追跡も行いません。つまり、名前の変更やコピーは記録されません。代わりに、名前の変更とコピーの検出を行います。あなたはリネームでの検出を要求することができますgit diff(とをgit show使用して)-Mオプションを、あなたが使用することによって変更されたファイルには、追加のコピー検出を要求できる-Cオプション(-C意味を-M)、あなたが持つすべてのファイルの中で、より高価なコピー検出を要求できる--find-copies-harder-C -Cを意味している(-C暗示され、-M)。git-diffのマンページを参照してください。

diff.renamesブール値をtrueに設定することで常に名前の変更の検出を行うようにgitを設定することもできます(trueまたはなど1)。また、copyまたはに設定することで、コピーの検出も行うようgitに要求することもできますcopiesgit-configのマンページを参照してください。

-lオプションgit diffと関連する設定変数も確認してくださいdiff.renameLimit


git log <pathspec>Gitでは動作が異なることに注意してください。<pathspec>パスの区切り文字のセットがここにあります。パスは(サブ)ディレクトリ名でもかまいません。名前の変更とコピーの検出が機能するようになる前に、履歴をフィルタリングして簡素化します。名前の変更とコピーを追跡したい場合git log --follow <filename>は、(これは現在少し制限があり、単一ファイルに対してのみ機能します)を使用します。


1
@allyourcode:何が混乱しているのですか?デフォルトでコピー検出をオンにするにはdiff.renamescopies(たとえば「git config diff.renames copies」)に設定します。私はそれが少し直観に反することに同意します。
JakubNarębski、2010

解析できないように見えるセクションの1つは、「デフォルトで名前変更検出を実行するように要求することもできます」です。diff.renamesが使用できる4つの値(true、1、copy、copys)があり、それらはすべて同じことをしていると言っていますか?
allyourcode 2010

1
@allyourcode:すみません、これに気づきませんでした。直しました、ありがとう。
JakubNarębski10年

4
@peschü:Gitは、コンテンツアドレス指定されたオブジェクトデータベースをリポジトリストレージとして使用します。ファイルのコンテンツは、コンテンツのSHA-1ハッシュ(タイプ+長さ+コンテンツ)であるアドレスの下の「blob」コンテンツに格納されます。つまり、指定されたコンテンツは1回だけ保存されます。Nb。この自動重複排除が、git pack形式を使用して「bup」バックアップシステムを作成する理由になりました。
JakubNarębski2014年

1
以下のソリューションとは異なり、これは範囲内の変更追​​跡では機能しません。Gitログでは、範囲の引数(git log -L123,456:file.xyz)を使用できますが、名前の変更は正しく行われますが、コピーはできません。その場合、-followを渡すことはできません。また、AFAICT、これはgit blameでは機能しません。
クレメント

57

2020-05-19:次のソリューションには、元のファイルのログを変更しない、マージの競合を作成しない、およびより短いという利点があります。

コピーしたファイルの履歴を3つのコミットでGitに検出させることができます。

  • コピーする代わりに、新しいブランチに切り替えて、ファイルを新しい場所に移動します。
  • そこで元のファイルを再度追加します。
  • no-fast-forwardオプションを使用して、新しいブランチを元のブランチにマージします--no-ff

(クレジットはRaymond Chenに送られます。)


前者のソリューションには4つのコミットがありました。

  • コピーする代わりに、新しいブランチに切り替えて、ファイルを新しい場所に移動します。
  • 元のブランチに切り替えて、ファイルの名前を変更します。
  • 新しいブランチを元のブランチにマージし、両方のファイルを保持することで、些細な競合を解決します。
  • 別のコミットで元のファイル名を復元します。

https://stackoverflow.com/a/44036771/1389680から取得したソリューション。)


7
シンプルさ、簡潔さ、100%...この答えは公共サービスです...目に見えるすべてのものに
賛成

1
どのような違いmoverename
vovan

@vovanあなたはbash mvで両方の操作に使用するという事実を言及していますか?ファイルのディレクトリを変更する必要がある場合は 'move'を使用し、変更しない場合は 'rename'を使用していました。
Robert Pollak

1
私はこの(新しい)レシピに従ってみましたが、うまくいきませんでした。実際のコマンドを表示すると役立つ場合があります。
グレッグリンダール

@RobertPollak私はこれのさまざまなバージョンを試しましたが、うまくいきませんでした。「ファイルを移動する」とはどういう意味git mv orig newですか?「原文を読んだ」とはどういう意味cp new orig && git add origですか?
ᆼᆺᆼ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.