让Git确认以前移动的文件


72

我不加思索地手动移动了一堆文件,并且找不到找到git的方法来识别文件只是移动的,而不是实际上不同的文件。除了删除旧文件并添加新文件(从而丢失历史记录),或者使用git-mv重做所有更改之外,还有其他方法吗?


5
Git自动获取文件的副本和移动。您为什么说它没有采取行动?
杰里米·沃尔

1
重复?stackoverflow.com/questions/433111/… ...在另一个问题上的一些好答案(至少对我有所帮助!)
Drew Noakes 2010年

编辑:我刚刚注意到,只要我先调用“ git commit -a”,“ git log”在移动的文件上就可以正常工作。

2
@JeremyWall我发现除非我明确使用git,否则git经常会错误地移动文件git mv
沃伦·露

Answers:


22

我认为它已经做到了。现在,我可能是错的,但是我读过git会根据文件的内容而不是基于文件系统中的位置或基于增量/差异来跟踪文件。在堆栈中,我认为它显示的就像是先删除文件再重新添加文件一样,但是由于前面提到的git跟踪内容的方式,我认为我已经尝试过一次并且仍然保持了历史记录。

仍然对某人验证我是否正确会有所帮助。对不起,如果我误解了你的问题。


18
这是对的。移动文件(分别在旧文件和新文件上分别使用“ git rm”和“ git add”)与使用“ git mv”之间应该没有区别。迈克尔:如果问题是您没有在“ git log FILE”中看到移动前的历史记录,请尝试使用“ git log --follow FILE”。
菲尔

9
没为我工作。Git看到该文件已删除,正在添加新文件。不知道我做错了什么。可能是个位存储桶问题,因为它看起来像Git在执行提交时检测到文件已重命名。
詹姆斯·麦克马洪

2
这全都取决于文件在移动后是多么的笨拙。如果将dummy.class重命名为clean_refactor.clas,则很可能会通过至少重命名类名来更改文件的内容。这些更改可能会使git无法意识到dummy.class和clean_refactor.class属于同一历史:(
Rafa

2
@JorgeIsraelPeña只是重命名文件不会有问题。但是通常您会在某些重构过程中重命名文件,并且与该重构相关的代码更改会混淆git。
拉法

1
@JorgeIsraelPeña是的,我知道。因此,我的咆哮:)在svn中,文件的历史不会丢失,包括其重构在内。我将在日志中看到,类B曾经被命名为A,并且被重构为
B。– Rafa

72

要让git删除已经删除或移动的文件,只需输入

git add -u

8
+1:谢谢,这正是所缺少的。如果git status不进行移动或重命名,请对其进行git add -u修复。
rsenna 2011年

11
您能解释一下这到底在做什么吗?
OlivierBlanvillain

5
@OlivierBlanvillain:'git add -u'分阶段git跟踪的所有文件,并且在工作目录中也已更改。请注意,如果您将文件移动到Git未跟踪的目录,则'add -u'不会检测到该移动。如果以后将目标目录添加到Git并重新执行“ add -u”,则Git将正确地进行移动。
JS。

请注意,如果您不想暂存其他文件,则应指定文件名。
wjandrea

11

git不会跟踪单个文件的历史记录,并且不会特别处理移动和复制,即没有特殊的元数据指示发生移动或复制。相反,每个git commit都是工作树的完整快照。

如果您想查看移动,git log-M除了提供列出哪些文件已更改的选项之外,还可以提供其他选项,例如

git log --summary -M

git 将查看提交历史记录中的相邻树,并推断每次提交是否移动了任何文件。

要查找副本和重命名,可以使用该-C选项,您可以提供两次,以使git看起来更难找到可能的副本源,但会牺牲一些性能。

git log --summary -M -C -C

请注意,随着Git并不保存文件历史记录(仅提交历史),即使你没有git rmgit mv文件,你就不会丢失任何历史。路径中的所有更改仍将被记录并显示在中git log


2
您还可以在(存储库配置)或(用户的配置)中将diff.renamesconfig变量设置为。有关详细信息,请参见git-config联机帮助页。true.git/config~/.gitconfig
JakubNarębski09年


1

您可以将新文件移动/重命名为它的旧名称和git之外的路径,然后用于暂存git mv移动。例如在bash中:

mv $NEW $OLD && git mv $OLD $NEW

它有点麻烦1,特别是如果您必须手动操作。但是它的优势在于,它可以保留其他更改,例如未命名的命名空间或类名的更改,因此您可以检查它们,并且仅在有意这样做时才对其进行更改。


1 我希望找到一个更好的替代方法,并在找到它时更新我的​​答案。

例子:我移动了一堆文件 oldDirnewDir及与其他一些积极的变化开始。现在,我要检查进行了哪些其他修改。使用 结果(一行):

git status --short |
gawk '/^\?\?/ && match($0, /newDir\/(*.\.cs)/, a) {print "newDir/" a[1] " " "oldDir/" a[1]}' |
xargs -n 2 bash -c 'mv $0 $1; git mv $1 $0'

现在git status将重命名显示为“要提交的更改”,并将文本修改显示为“未暂存用于提交的更改”


我可能只是一个旧的git,但是如果文件更改太大,它将$ OLD标记为已删除,将$ NEW标记为已创建。任何编辑都应在“ git mv”之前提交。
jbo5112 '19

0

它发生在我身上,当我移动和编辑文件时,它不再将其识别为正在移动的文件,而是一个新文件,因此我失去了历史记录。

我要做的是创建2个单独的提交,一个是我移动文件时提交的,然后是另一个编辑文件。这样我就保留了历史。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.