git重命名vs删除重复启发式



假设我将一个文件从a.txt重命名为b.txt。Git可以正确检测到;很好。这里有一个更棘手的例子。我有两个相同的文件,x.txty.txt。我想对它们进行重复数据删除,并将结果命名为z.txt。Git报告一次重命名和一次删除。问题是,哪个文件被重命名,哪些被删除?谁在乎呢,它们是一样的,对吧?但是只有重命名的才会保留其历史记录,我确实在那里设置了首选项。

如果你有偏好,不要依赖git的重复数据删除。使用git mv x.txt z.txt显式重命名您想要的,并使用git rm y.txt删除另一个。注意:这假定您希望保留x.txt的历史记录。如果您想保留y.txt的历史记录,请在上述命令中交换x.txty.txt

这是hackish,但它可以通过欺骗git自己来解决:在单独的分支上进行重命名,并迫使git将两个文件合并在一起。

git checkout -b rename-branch
git mv a.txt b.txt
git commit -m "Renaming file"
# if you did a git blame of b.txt, it would _follow_ a.txt history, right?
git checkout main
git merge --no-ff --no-commit rename-branch
git checkout HEAD -- a.txt # get the file back
git commit -m "Not really renaming file"

直接复制,你会得到:

$ git log --graph --oneline --name-status
* 70f03aa (HEAD -> master) COpying file straight
| A     new_file.txt
* efc04f3 (first) First commit for file
A     hello_world.txt
$ git blame -s new_file.txt
70f03aab 1) I am here
70f03aab 2) 
70f03aab 3) Yes I am
$ git blame -s hello_world.txt
^efc04f3 1) I am here
^efc04f3 2) 
^efc04f3 3) Yes I am

在旁边使用重命名并获得文件,您将得到:

$ git log --oneline --graph master2 --name-status
*   30b76ab (HEAD, master2) Not really renaming
|  
| * 652921f Renaming file
|/  
|   R100        hello_world.txt new_file.txt
* efc04f3 (first) First commit for file
A     hello_world.txt
$ git blame -s new_file.txt
^efc04f3 hello_world.txt 1) I am here
^efc04f3 hello_world.txt 2) 
^efc04f3 hello_world.txt 3) Yes I am
$ git blame -s hello_world.txt
^efc04f3 1) I am here
^efc04f3 2) 
^efc04f3 3) Yes I am

的基本原理是,如果你想查看原始文件的历史记录,git可以毫无问题地完成它....如果你想在copy上做,那么git将跟随重命名所在的单独分支,然后它将能够跳转到copy后面的原始文件,仅仅因为它是在那个分支上完成的。