`git log--follow--graph`跳过提交 安装程序

`git log--follow--graph`跳过提交 安装程序,git,git-log,Git,Git Log,下面是一个用于复制我的测试存储库的bash片段: git version 2.11.0.windows.1 最后,git log--graph--pretty=oneline--abbrev commit打印: 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 e

下面是一个用于复制我的测试存储库的bash片段:

git version 2.11.0.windows.1
最后,
git log--graph--pretty=oneline--abbrev commit
打印:

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
*   06b5bb7 Merge branch 'feature'
|\
| * 07ccfb6 Change
* | 448ad99 Move
|/
* 31eae74 First commit

问题 现在,我想获取
b.txt
(ex-
b.txt
)的完整日志。
git log--graph--pretty=oneline--abbrev commit--follow--b.txt
打印:

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
*   06b5bb7 Merge branch 'feature'
|\
| * 07ccfb6 Change
* | 448ad99 Move
|/
* 31eae74 First commit
如您所见,
Change
commit没有列出,即使它修改了文件

我想我已经找到了
--topo order
--graph
隐式使用的原因,因为添加
--date order
会使提交返回,但这可能是偶然的

此外,添加
-m
会显示合并提交(这很好)和
更改
提交,但合并提交会重复:

...
* | 1a07e48 Move
|/
* 5ff73f6 First commit
问题: 我错过了什么来解释我目睹的奇怪行为?

如何在重命名之后清晰地显示所有更改文件的提交?

您正被
git log
廉价而低劣的
--follow
实现所困扰,再加上
git log
通常甚至不会查看合并内部的事实

基本上,
--follow
通过更改要查找的文件名在内部工作。它不记得这两个名称,因此当线性化算法(通过优先级队列的广度优先搜索)进入合并的另一个分支时,它的名称是错误的。您是正确的,提交访问的顺序很重要,因为Git在推断重命名时更改了它搜索的文件名

在此图中(看起来您多次运行脚本,因为哈希值发生了变化。此处的哈希值来自第一个示例):

git log
将访问commit
06b5bb7
,并将
448ad99
07ccfb6
放在队列上。使用默认拓扑顺序,它将下次访问
448ad99
,检查差异,并查看重命名。它现在正在寻找
a.txt
,而不是
b.txt
。选择提交
448ad99
,因此
git log
将打印到输出;Git将
31eae74
添加到访问队列中。接下来,Git将访问
07ccfb6
,但它现在正在查找
a.txt
,因此不会选择此提交。Git将
31eae74
添加到访问队列中(但它已经在那里了,所以这是一个no-op)。最后,Git访问
31eae74
;将提交的树与空树进行比较,Git会找到一个添加的
a.txt
,因此会选择此提交

请注意,如果Git在
448ad99
之前访问了
07ccfb6
,它会选择两者,因为在开始时它正在查找
b.txt

-m
标志通过将合并“拆分”为两个单独的内部“虚拟提交”(使用相同的树,但将
(from…
)添加到它们的“名称”中,以便能够区分哪个虚拟提交是由哪个父级产生的)。这样做的副作用是保留两个拆分合并并查看它们的差异(因为拆分此合并的结果是两个普通的非合并提交)。现在请注意,在第二个Git Visites commit
36c80a8(来自1a07e48)
,diff
1a07e48
36c80a8
的示例中,它使用了新的存储库及其新的不同哈希,看到对
b.txt
的更改并选择提交,然后将
1a07e48
放在访问队列上。接下来,它访问commit
36c80a8(从05116f1开始)
,diff
05116f1
vs
36c80a8
,并将
05116f1
放在访问队列上。从这里看,剩下的是相当明显的

如何在重命名之后清晰地显示更改文件的所有提交

Git的答案是不能,至少不能使用Git内置的东西

您可以(有时)通过将
--cc
-c
添加到您的
git log
命令中来更进一步。这使得
git log
可以查看合并提交,执行git所称的操作。但这并不一定有效,因为这是一句关键的话:

请注意,组合差异仅列出从所有父级修改的文件

下面是我通过添加
--cc
得到的信息(注意,
..
git log
的输出中确实存在):


但是,从根本上说,您需要
git log
在合并提交时更清楚地了解文件重命名,并让它使用旧文件名在任何段中查找旧名称,使用新名称在任何段中查找新名称。这将要求
git log
在每个合并中内部使用(大部分)
-m
选项,即,将每个合并拆分为N个单独的diff,每个父级一个,以便找到哪些分支具有哪些重命名,然后保留一个列表,列出要使用的名称以及合并的哪些分支。但是,当分叉重新组合在一起时,也就是说,当合并的多个分支(在我们的反向方向上成为分叉)重新连接时,不清楚哪个名称是正确的名称

开枪。好吧,无论如何,谢谢你对这个问题的全面分析:)
$ 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