git version 2.11.0.windows.1
Run Code Online (Sandbox Code Playgroud)
这是一个重现我的测试存储库的bash片段:
git init
# Create a file
echo Hello > a.txt
git add a.txt
git commit -m 'First commit'
# Change it on one branch
git checkout -b feature
echo Hi > a.txt
git commit -am 'Change'
# Rename it on the other
git checkout master
git mv a.txt b.txt
git commit -m 'Move'
# Merge both changes
git merge --no-edit feature
Run Code Online (Sandbox Code Playgroud)
最后,git log --graph --pretty=oneline --abbrev-commit打印:
* 06b5bb7 Merge branch 'feature'
|\
| * 07ccfb6 Change
* | 448ad99 Move
|/
* 31eae74 First commit
Run Code Online (Sandbox Code Playgroud)
现在,我想得到b.txt(ex- b.txt)的完整日志.
git log --graph --pretty=oneline --abbrev-commit --follow -- b.txt打印:
...
* | 1a07e48 Move
|/
* 5ff73f6 First commit
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,Change提交未列出,即使它没有修改该文件.
我想我已经跟踪下来的隐式使用的--topo-order通过--graph,因为增加--date-order带来的提交回来了,但可能是机会.
此外,添加-m显示合并提交(这很好)和Change提交,但然后重复合并提交:
* 36c80a8 (from 1a07e48) Merge branch 'feature'
|\
| | 36c80a8 (from 05116f1) Merge branch 'feature'
| * 05116f1 Change
* | 1a07e48 Move
|/
* 5ff73f6 First commit
Run Code Online (Sandbox Code Playgroud)
我想要解释我目睹的奇怪行为是什么?
如何通过重命名完全显示更改文件的所有提交?
你被git log廉价和低俗的实施所困扰--follow,加上git log通常甚至看不到内部融合的事实.
从根本上说,--follow通过更改它正在寻找的文件的名称在内部工作.它不记得这两个名称,所以当线性化算法(通过优先级队列的广度优先搜索)下降到合并的另一条腿时,它的名称错误.你是正确的,提交访问的顺序很重要,因为当Git推断重命名时,Git改变了它正在搜索的文件的名称.
在此图中(看起来您多次运行脚本,因为哈希值已更改 - 此处的哈希值来自第一个样本):
* 06b5bb7 Merge branch 'feature'
|\
| * 07ccfb6 Change
* | 448ad99 Move
|/
* 31eae74 First commit
Run Code Online (Sandbox Code Playgroud)
git log将访问提交06b5bb7,并把448ad99和07ccfb6队列.使用默认的拓扑订单,它将在下次访问448ad99时检查差异,并查看重命名.现在正在寻找a.txt而不是b.txt.448ad99选择提交,git log将其打印到输出; 和Git添加31eae74到访问队列.接下来,Git访问07ccfb6,但现在正在查找,a.txt因此未选择此提交.Git添加31eae74到访问队列(但它已经存在,所以这是一个无操作).最后,Git访问31eae74; 将该提交的树与空树进行比较,Git找到一个添加的内容,a.txt以便选择此提交.
需要注意的是有Git的访问07ccfb6 之前 448ad99,它会同时选中,因为它正在寻找的开始b.txt.
该-m标志的工作原理是将一个合并"拆分"为两个独立的内部"虚拟提交"(使用相同的树,但(from ...)添加到其"名称"中,以便能够分辨哪个虚拟提交来自哪个父级).这具有保留两个拆分合并并查看它们的差异的副作用(因为拆分此合并的结果是两个普通的非合并提交).现在请注意,这会在第二个示例中使用您的新存储库及其新的不同哈希 - Git访问提交36c80a8 (from 1a07e48),差异1a07e48vs 36c80a8,查看更改b.txt并选择提交,并放置1a07e48访问队列.接下来,它访问commit 36c80a8 (from 05116f1),diffs 05116f1vs 36c80a8,并放入05116f1访问队列.其余部分从这里开始相当明显.
如何通过重命名完全显示更改文件的所有提交?
Git的答案是你不能,至少不能使用Git中内置的东西.
你可以(有时)通过添加--cc或命令-c来更近一点git log.这使得git log查看内部合并提交,执行Git所谓的组合差异.但这无论如何都不一定有效,因为隐藏在文档的不同部分的是这个关键句子:
请注意,组合差异仅列出从所有父项修改的文件.
这是我--cc添加的内容(注意,...字面意思是在git log输出中):
$ git log --graph --oneline --follow --cc -- b.txt
* e5a17d7 (HEAD -> master) Merge branch 'feature'
|\
| |
...
* | 52e75c9 Move
|/
| diff --git a/a.txt b/b.txt
| similarity index 100%
| rename from a.txt
| rename to b.txt
* 7590cfd First commit
diff --git a/a.txt b/a.txt
new file mode 100644
index 0000000..e965047
--- /dev/null
+++ b/a.txt
@@ -0,0 +1 @@
+Hello
Run Code Online (Sandbox Code Playgroud)
但是,从根本上说,你需要git log更多地了解合并提交时的文件重命名,并让它使用旧文件名在任何一条腿上查找旧名称,并使用新名称查找任何一条腿的新名称.这将需要在每个合并内部git log使用(大部分)-m选项 - 即,将每个合并拆分为N个单独的差异,每个父级一个,以便找到哪些分支具有重命名 - 然后保留要使用的名称的列表合并哪些分支.但是当叉子一起回来时,即当合并的多个支腿(在我们的反方向上成为一个叉子)重新加入时,不清楚哪个名称是正确的名称!
| 归档时间: |
|
| 查看次数: |
494 次 |
| 最近记录: |