Git

為什麼 git repo 的 cp -uav 對某些文件顯示“已刪除”?

  • May 24, 2017

我曾經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選項的一個怪癖。

引用自:https://unix.stackexchange.com/questions/366936