為什麼 git repo 的 cp -uav 對某些文件顯示“已刪除”?
我曾經
cp -uav
更新一個 git repo 的副本,包括未送出的文件。為什麼它說它正在刪除文件?它看起來像這樣:
$ 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
我可以按如下方式重現上述消息:
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/bf350cea1fb4fd036235d7e6c36eb600e68885 文件存在,0)
取消連結(“複製/repos/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885”)= 0
linkat(AT_FDCWD,“複製/repos/g/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885”,AT_FDCWD,“複製/repos/h/.git/objects/2b/bf350cea1fb4fd036235d7e6c36eb600e68885”,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
選項的一個怪癖。