我曾經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
,記錄為
--preserve[=ATTR_LIST]
保留指定的屬性(預設:模式、所有權、時間戳記),如果可能的話附加屬性:上下文、連結、xattr、全部
取消連結作為硬連結保留的一部分發生:
。 85 ", 0) = -1 EEXIST(檔案存在)
取消連結(「複製/儲存庫/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885」)= 0
。 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
選項的一個怪癖。