cp -uav
コミットされていないファイルを含むgitリポジトリのコピーを更新したことがあります。
ファイルを削除すると言うのはなぜですか?次のようになります。
$ cp -uav repos copy
removed 'copy/repos/h/.git/objects/e6/9de29bb2d1d6434b8b29ae775ad8c2e48c5391'
removed 'copy/repos/h/.git/objects/3b/b3f834dd037db9298b10d71e0cd7383000fa1c'
removed 'copy/repos/h/.git/objects/49/6d6428b9cf92981dc9495211e6e1120fb6f2ba'
removed 'copy/repos/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885'
$ rpm -q --whatprovides `which cp`
coreutils-8.25-17.fc25.x86_64
ベストアンサー1
上記のメッセージを次のように再現できます。
mkdir test; cd test
mkdir repos; cd repos
mkdir g; cd g
git init
touch a
git add a
git commit -m test
cd ..
git clone g h
cd ..
mkdir copy
cp -ua repos copy
cp -uav repos copy
cp -ua
以下のコマンドを実行すると、実際にファイルをstrace
削除()していることがわかります。unlink
何が起こると、のオブジェクトがのオブジェクトへのrepo/h/.git/objects
ハードリンクになりますrepo/g/.git/objects
。 (元の場合、元のプライマリリポジトリのレプリカとして作成されたサブリポジトリを含むリポジトリを複製しました。)
cp -a
を意味しcp --preserve
、次のように記録されます。
--保存[=ATTR_LIST]
指定された属性(デフォルト:モード、所有権、タイムスタンプ)、可能であれば追加の属性(コンテキスト、リンク、xattr、すべて)を保持します。
リンク解除は、ハードリンク保持の一部として発生します。
linkat(AT_FDCWD,"/repos/g/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885 コピー", AT_FDCWD,"/repos/h/.git/objects/2b/bf35c6 8 コピー 85" ", 0) = -1 EEXIST(ファイルこの存在)
unlink("コピー/ストア/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885") = 0
linkat(AT_FDCWD,"/repos/g/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885 コピー", AT_FDCWD,"/repos/h/.git/objects/2b/bf35c6 8 コピー 85"”, 0) = 0
なぜそれが私をそんなに混乱させるメッセージを生成するのですか?
このコードでは-u
()が完全に実装されていないようです。--update
これは主に不要なデータ再コピーを防ぐためのパフォーマンス最適化です。ハードリンクを作成するときにデータをコピーする必要はありません。
ドキュメントからcp
ファイルも削除する必要がある他のシナリオを表示できます。
-f, --force if an existing destination file cannot be opened, remove it and try again (this option is ignored when the -n option is also used)
この場合、-f
「強制」する必要がある特定のファイルを表示しようとする可能性があることがわかります。
中断された場合は、削除を表示することも役に立ちますcp
。そうしないと、ユーザーはファイルが(中間段階で)ターゲットから削除された可能性があることに気づかないでしょう。
最後の質問は、リンクを再生成するときに混乱を避けるためにメッセージを表示しない理由です。私はこれが-u
このオプションの特徴だと思います。