谁在git中删除了我的更改?

19

过去30分钟里我一直遇到这个问题:我的某些修改在一个文件中消失了,而我不知道是何时发生的。我想知道谁做了这件事!

我开始寻找包含我文件的修订版本:

git grep <searched_string> $(git rev-list --all) -- <file>

是指文件的路径或类似于*.gsp的通配符

我有许多修订版本,我查看最后一个版本,并尝试获取其子版本(认为第一个子版本应该是我的更改消失的第一个版本)

git rev-list --children <revision_id>

是指从上一个命令的最后一行开始的前40个字符

快接近了!我正在查看输出的开头,取第一个子元素然后运行

git log <revision_id_s_first_child> --stat

然后我查看输出,找到了修改文件的人和时间!(结果发现是我的责任……)

有没有更快的方法可以做到这一点?(git blame 不会显示已删除的内容)


你尝试过使用“鹤嘴锄”(pickaxe)的方式,即 git log -S 吗? - Greg Hewgill
2
可能是重复的问题,参考如何“责备”已删除的行 - hypehuman
4个回答

29

git blame有一个--reverse选项,它接受一系列提交并显示在删除之前最后存在该行的最后提交。 所以,你可以找到一个你知道这些行存在的提交,比如说例如abcdef01,然后显示删除前的最后提交:

git blame --reverse abcdef01..HEAD -- <file>

1
很遗憾,git gui blame不支持--reverse - Mikko Rantalainen
这里告诉我什么- 9597c8db (XYZ 2014-05-27 10:18:51 -0700 93) 8e4dbc16 (XYZ 2014-05-06 19:08:29 +0100 94) 1b4dbc16 (XYZ 2014-05-06 19:08:29 +0100 95)-700和+100是什么意思? - R11G
这些是时区偏移量。-0700 可能是美国西部,比格林威治标准时间晚7小时。+0100 可能是欧洲,比格林威治标准时间早1小时。 - Karl Bielefeldt
7
实际上,“git blame --reverse”命令显示的是“在删除行之前存在的最后一次提交”。但是,该提交可能与所考虑的文件无关。实际上删除该行的是下一个提交:请参见https://dev59.com/XHE95IYBdhLWcg3wi-ie#9870218找到下一个提交。是否有人知道是否可以让“git blame --reverse”显示每行相关的提交,而不是默认情况下显示的不相关提交? - BlackShift

10

如果你知道一些在被删除的行中出现的子字符串,那么你可以使用-G选项来查找引入添加或删除包含该子字符串的行的更改的提交。例如,如果你知道单词“pandemic”出现在消失的行中,你可以执行以下操作:

git log -Gpandemic -p

(-G 参数可以是一个正则表达式。) 这个选项是最近添加到 git 中的 - 如果它不起作用,请尝试使用 -S,它具有略微不同的语义,但应该有类似的效果。


-G 对我似乎不起作用。-S 会显示添加的时间,而不是删除的时间。 - standup75
-S 应该在添加或删除时向您显示(请参阅man页面)。但是,-S 的行为略有些奇怪 - 它查看提交之前版本和提交中字符串出现的次数 - 因此,如果您只是移动了一行,那么它将无法检测到。这就是为什么 -G 通常更可取,但它只在 git 版本 1.7.4 中引入。 - Mark Longair
我们得到了1.7.3.4。无论如何,感谢反馈,确实很有趣。尽管我搜索的字符串在下一个版本中根本不存在,但仍然看不到我的更改已被删除。 - standup75
在合并(冲突)期间,您可能需要使用“-c”或“-cc”来显示删除。请参见此答案 - cfi

3
请注意,自Git 2.11(2016年第四季度)以来,如果您想查看特定提交和当前提交之间的提交,则无需指定..HEAD
因此,Karl Bielefeldt答案将是:
 git blame --reverse abcdef01 -- <file>

请参见 提交d993ce1(2016年6月14日),作者为Junio C Hamano(gitster
(由Junio C Hamano -- gitster --提交1172e16中合并,2016年10月10日)

责怪:将"blame --reverse OLD"解释为"blame --reverse OLD.."

常见的错误是说"git blame --reverse OLD path",期望命令行像询问路径中旧版本OLD中的行如何存活到当前提交一样智能化。

我们可以DWIM "OLD",而不总是要求范围的两端,这可能是一个拼写错误的"OLD..",以成为一个以当前提交为结束的范围。

git blame --reverse现在包括:

--reverse <rev>..<rev>:

走向历史前进而非后退。 不显示一行代码出现的修订版本,而是显示该行存在的最后一个修订版本。 这需要一个修订版本范围,如START..END,其中路径到责任存在于START。 为了方便起见,git blame --reverse START被视为git blame --reverse START..HEAD。 (注:{{link1:"dwim"是“Do What I Mean”的首字母缩写,意思是“做我想要的,而不是我说的”)

@KasunSiyambalapitiya 还不确定:你可以提一个新问题询问这个。 - VonC

1

git blame --reverse 可以让你接近被删除的代码行所在的位置。但它实际上并没有指向代码被删除的版本,而是指向了最后一次存在该行代码的版本。如果下一个版本是一个普通提交,那么你很幸运,已经找到了删除该代码行的版本。然而,如果下一个版本是一个合并提交,那么事情可能会变得有些复杂。作为创建difflame的努力的一部分,我解决了这个问题。如果你已经安装了Python,并愿意尝试,请不要再等待,告诉我它的表现如何。

https://github.com/eantoranz/difflame


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接