What's the purpose of git-mv?
据我所知,Git不需要跟踪文件重命名/移动/复制操作,所以真正的目的是什么?Git MV?该手册页没有特别描述…
它过时了吗?它是一个内部命令,而不是供普通用户使用吗?
1 | git mv oldname newname |
只是以下内容的简写:
1 2 3 | mv oldname newname git add newname git rm oldname |
也就是说,它会自动更新旧路径和新路径的索引。
来自官方gitfaq:
Git has a rename command
git mv , but that is just a convenience. The effect
is indistinguishable from removing the file and adding another with different
name and the same content
吉特只是想帮你猜你想做什么。它正在尽一切努力保护未被打破的历史。当然,这并不完美。因此,
考虑这个例子。从空回购开始,
1 2 3 4 5 6 7 8 | git init echo"First">a echo"Second">b git add * git commit -m"initial commit" mv a c mv b a git status |
结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 | # On branch master # Changes not staged for commit: # (use"git add/rm <file>..." to update what will be committed) # (use"git checkout -- <file>..." to discard changes in working directory) # # modified: a # deleted: b # # Untracked files: # (use"git add <file>..." to include in what will be committed) # # c no changes added to commit (use"git add" and/or"git commit -a") |
自动检测失败:.(还是这样?
1 2 3 4 5 6 7 8 9 | $ git add * $ git commit -m"change" $ git log c commit 0c5425be1121c20cc45df04734398dfbac689c39 Author: Sergey Orshanskiy <*****@gmail.com> Date: Sat Oct 12 00:24:56 2013 -0400 change |
然后
1 2 3 4 5 6 7 8 9 10 11 12 | $ git log --follow c Author: Sergey Orshanskiy <*****@gmail.com> Date: Sat Oct 12 00:24:56 2013 -0400 change commit 50c2a4604a27be2a1f4b95399d5e0f96c3dbf70a Author: Sergey Orshanskiy <*****@gmail.com> Date: Sat Oct 12 00:24:45 2013 -0400 initial commit |
现在尝试一下(实验时记得删除
1 2 3 4 5 6 7 | git init echo"First">a echo"Second">b git add * git commit -m"initial commit" git mv a c git status |
到现在为止,一直都还不错:
1 2 3 4 5 6 7 8 9 | # On branch master # Changes to be committed: # (use"git reset HEAD <file>..." to unstage) # # renamed: a -> c git mv b a git status |
现在,没有人是完美的:
1 2 3 4 5 6 7 8 | # On branch master # Changes to be committed: # (use"git reset HEAD <file>..." to unstage) # # modified: a # deleted: b # new file: c # |
真的?但当然……
1 2 3 4 | git add * git commit -m"change" git log c git log --follow c |
…结果和上面一样:只有
现在,小心重命名,因为任何一个选项都会产生奇怪的效果。例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | git init echo"First">a git add a git commit -m"initial a" echo"Second">b git add b git commit -m"initial b" git mv a c git commit -m"first move" git mv b a git commit -m"second move" git log --follow a commit 81b80f5690deec1864ebff294f875980216a059d Author: Sergey Orshanskiy <*****@gmail.com> Date: Sat Oct 12 00:35:58 2013 -0400 second move commit f284fba9dc8455295b1abdaae9cc6ee941b66e7f Author: Sergey Orshanskiy <*****@gmail.com> Date: Sat Oct 12 00:34:54 2013 -0400 initial b |
对比一下:
1 2 3 4 5 6 7 8 9 10 11 12 13 | git init echo"First">a git add a git commit -m"initial a" echo"Second">b git add b git commit -m"initial b" git mv a c git mv b a git commit -m"both moves at the same time" git log --follow a |
结果:
1 2 3 4 5 6 7 8 9 10 11 | commit 84bf29b01f32ea6b746857e0d8401654c4413ecd Author: Sergey Orshanskiy <*****@gmail.com> Date: Sat Oct 12 00:37:13 2013 -0400 both moves at the same time commit ec0de3c5358758ffda462913f6e6294731400455 Author: Sergey Orshanskiy <*****@gmail.com> Date: Sat Oct 12 00:36:52 2013 -0400 initial a |
不间断电源。。。现在历史回到了A开头,而不是B开头,这是错误的。所以,当我们一次做两个动作时,Git变得困惑,无法正确跟踪变化。顺便说一下,在我的实验中,同样的情况也发生在我删除/创建文件而不是使用
正如@charles所说,
这里真正的问题是"其他版本控制系统(如Subversion和Perforce)专门处理文件重命名"。为什么不吉特?"
Linus在http://permalink.gmane.org/gmane.comp.version-control.git/217上解释道:
Please stop this"track files" crap. Git tracks exactly what matters,
namely"collections of files". Nothing else is relevant, and even
thinking that it is relevant only limits your world-view. Notice how the
notion of CVS"annotate" always inevitably ends up limiting how people use
it. I think it's a totally useless piece of crap, and I've described
something that I think is a million times more useful, and it all fell out
exactly because I'm not limiting my thinking to the wrong model of the
world.
我还有另外一个用途是用于上面没有提到的
由于发现了
有一种特殊的情况,
Greg.Kindel在对cb贝利回答的评论中提到了这一点。
假设您在Mac上工作,并且有一个由Git管理的文件
你可以试试:
1 2 3 4 5 6 7 | $ mv Mytest.txt MyTest.txt overwrite MyTest.txt? (y/n [n]) y $ git status On branch master Your branch is up to date with 'origin/master'. nothing to commit, working tree clean |
哦,天哪。Git不承认文件有任何更改。
您可以使用以下方法来解决此问题:完全重命名文件,然后重新重命名:
1 2 3 4 5 6 7 8 9 10 11 12 13 | $ mv Mytest.txt temp.txt $ git rm Mytest.txt rm 'Mytest.txt' $ mv temp.txt MyTest.txt $ git add MyTest.txt $ git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use"git reset HEAD <file>..." to unstage) renamed: Mytest.txt -> MyTest.txt |
好哇!
或者你可以通过使用
1 2 3 4 5 6 7 8 9 | $ git mv Mytest.txt MyTest.txt $ git status On branch master Your branch is up to date with 'origin/master'. Changes to be committed: (use"git reset HEAD <file>..." to unstage) renamed: Mytest.txt -> MyTest.txt |