我已经创建了一个测试别名,在这个别名中,我希望能够只记录我正在使用的当前分支(请记住这是日志的简化版本,最后一个有更多细节,颜色和等等)。
我的别名看起来像这样:
test = "!git log \"$(git rev-parse --abbrev-ref HEAD)\""
但是当我输入git test
时,我得到了分支上的2个提交以及来自不同分支的所有先前提交(我不想要)。
任何的想法?谢谢
你在这里显示的别名没有错,你的期望(你对Git在“分支上”的意思)的想法是错误的:也就是说,你在“分支上”是什么意思,而Git的意思是“在一个分支上”分支“,根本不同意。
基本问题是Git分支并不意味着人们期望它们的含义。 (有人可能会认为这意味着Git是错误的。其他一些VCS如Mercurial定义了你希望Git定义它们的方式。)在Git中,一个分支名称只指向一个提交,Git称之为提交提交那个分支。
但是,每次提交都会指回先前或父提交的某个数字(通常是一个)。 Git使用它将提交串起来用于多种目的,包括用git log
显示它们。我们可以通过纸上或白板或StackOverflow答案绘制这个,用一个箭头绘制分支名称,指向分支中包含的最后一个提交,然后进行该提交 - 其“真名” “是那些丑陋的提交哈希ID之一,但我们将在这里使用单个字母 - 从中有一个箭头,指向其父级,依此类推:
... <-F <-G <-H <-- master
git log
所做的是从分支名称指向的提交开始,并显示它。然后它移动到提交的父级,并显示。然后它进一步向后移动(向左)并显示提交,依此类推
所有Git内部链接总是向后,所以只要我们将更新的提交放在右边,我们就不需要绘制内部箭头了。我们只知道他们倒退了。那么让我们绘制一个更复杂的设置:
...--F--G--H <-- master
\
I--J <-- feature
名称feature
指向提交J
,因此提交J
在功能分支上。承诺J
回到I
,指向回到H
的G
,依此类推。所以每次提交都在分支feature
上,即使提交H
也是分支master
的提示。通过H
提交的所有内容都在master
上,所以通过H
的提交都在两个分支上。
你想在这里做什么,而不是记录当前分支中包含的所有提交 - 简单的git log
就足够了 - 是要求Git记录当前分支中包含但未包含在其他分支中的提交(es )。棘手的部分在于弄清楚如何排除这些提交。
一种方法是列出每个分支名称,然后去掉当前分支名称,然后告诉git log
:列出当前分支中包含的每个提交,从HEAD
开始,但在到达任何其他分支中包含的任何提交时停止列表。要做到这一点,你可以得到当前的分支名称(正如你现在所做的那样,或以其他方式),并从所有分支的列表中排除(你会得到某种方式):
git log HEAD --not br1 br2 br3 br4
(如果其他四个分支通过br1
命名为br4
)。
但这通常不是必需的。通常,每当您在某个分支上工作时,您将指定一些其他名称 - 有时是另一个分支名称,有时候像origin/master
这样的远程跟踪名称 - 作为当前分支的上游。每个分支只能有一个上游设置(或根本没有设置),一旦你有一个上游设置,你可以使用符号表示法@{upstream}
或短版本@{u}
来引用它:
git log HEAD --not @{u}
这有一个较短的语法,因为它经常有用:为一个提交说明符添加一个帽子^
字符意味着“不”,所以你可以写:
git log HEAD ^@{u}
然后有一个更短的语法,因为这是如此常见:
git log @{u}..HEAD
字面意思是指从当前HEAD提交可到达的所有提交,除了从当前分支的上游可到达的所有提交。
所以你可能想要的只是@{u}..HEAD
符号。这与明确排除所有其他分支不同。例如,假设我们有一个图形看起来像这样:
M <-- origin/br2
/
...--H <-- origin/master, origin/br1
\
I--J <-- br1
\
K--L <-- br2 (HEAD)
进一步假设br2
的上游是origin/br2
。要求origin/br2..br2
(即@{u}..HEAD
)中的提交意味着你将选择提交L
,K
,J
和I
。要求br2
中包含的提交但没有其他分支(即,不是br1
)将只获得L
和K
。如果只得到L
和K
- 就是你想要的,那么你实际上需要枚举所有的分支。
(枚举所有分支的技巧是使用git for-each-ref
和refs/heads/
前缀。你应该考虑使用git symbolic-ref
来读取当前的分支名称,如果你要编写很多脚本或花哨的别名。这些命令,git for-each-ref
和Gazxswpoi一样,是Git所说的管道命令,用于编写脚本和复杂的别名。它们的行为更加严格,针对计算机使用,而不是像git symbolic-ref
或git log
这样的“面向用户”的命令。 “面向用户”有点可笑,但他们显然更加注重用户,例如,git diff
。)
1这简化了一下。在查看多个分支名称或遵循多个父项的合并提交的情况下,git diff-tree
必须以某种方式线性化图形拓扑。它通过优先级队列执行此操作,显示“最高优先级”提交,并将该提交的父项添加到队列中。然而,对于简单的线性链,Git在历史中向后移动的想法就足够了。