git 别名不只记录我想要的分支

git alias not logging only the branch i want

我创建了一个测试别名,在这个别名中,我希望能够只记录我所在的当前分支(请记住,这是日志的简化版本,最后一个有办法更多细节、颜色等)。

我的别名是这样的:

test = "!git log \"$(git rev-parse --abbrev-ref HEAD)\""

但是当我键入 git test 时,我得到了分支上的 2 次提交以及来自不同分支的所有先前提交(我不想要)。

有什么想法吗?谢谢

这里显示的你的别名没有错,是你的期望(你认为 Git 是 "on a branch" 的意思)是错误的:那是,"on a branch"是什么意思,Git"on a branch"是什么意思,根本不同意.

基本问题是 Git 分支并不代表人们期望的意思。 (有人可能会争辩说这意味着 Git 是错误的。其他一些 VCS,例如 Mercurial 定义分支的方式是您希望 Git 定义它们的方式。)在 Git 中,一个分支 name 仅指向 one 提交,Git 调用该分支的 tip commit

但是,每个提交都指向以前或 parent 提交的某个数量(通常是一个)。 Git 出于多种目的使用它来将提交串在一起,包括使用 git log 显示它们。我们可以通过在纸上或白板上或在 Whosebug 答案中绘制分支名称,并用箭头从中引出,指向包含在分支中的 last 提交,然后让那个提交——它的 "true name" 是那些丑陋的大提交哈希 ID 之一,但我们在这里使用单个字母——有一个箭头指向它的父级,等等:

... <-F <-G <-H   <-- master

git log所做的是从分支名称指向的提交开始,并显示它。然后它移动到提交的父级,并显示它。然后它会及时向后移动(向左)并显示该提交,依此类推。1

所有Git内部链接总是向后的,所以只要我们把较新的提交放在右边,我们就不需要画内部箭头。我们只知道他们倒退了。那么让我们绘制一个更复杂的设置:

...--F--G--H   <-- master
            \
             I--J   <-- feature

名称feature 指向提交J,因此提交J 在功能分支上。提交 J 指向 I,后者指向 H,后者指向 G,依此类推。所以每个提交都在分支feature上,即使提交H也是也是分支[=28的尖端提交=].通过 H 的提交都在 master 上,因此通过 H 的提交在 两个分支上

您在这里要做的不是记录当前分支中包含的所有提交——一个简单的 git log 就足够了——而是要求 Git 记录包含的提交在您当前的分支 包含在其他一些分支 中。棘手的部分在于弄清楚如何排除那些提交。

一种方法是列出每个分支名称,然后去掉当前分支名称,然后告诉 git log为我列出当前分支中包含的每个提交,从 HEAD,但在到达任何其他分支中包含的任何提交时停止列出。 为此,您可以获取当前分支名称(就像现在一样,或以其他方式)并将其排除在外所有分支的列表(你会以某种方式获得):

git log HEAD --not br1 br2 br3 br4

(如果其他四个分支被命名为br1br4)。

不过,这通常不是必需的。一般来说,每当你在某个分支上工作时,你都会指定一些其他名称——有时是另一个分支名称,有时是 远程跟踪名称,如 origin/master——作为当前分支的名称上游。每个分支只能有一个上游设置(或根本没有设置),一旦你有一个上游设置,你可以使用符号符号 @{upstream} 或简称 @{u} 来引用它:

git log HEAD --not @{u}

这里有一个更短的语法,因为它经常有用:在提交说明符前加上帽子 ^ 字符表示 "not",所以你可以写:

git log HEAD ^@{u}

还有一个更短的语法,因为这个很常见:

git log @{u}..HEAD

字面意思是从当前 HEAD 提交可到达的所有提交,除了从当前分支的上游可到达的所有提交。

所以您可能需要的只是 @{u}..HEAD 表示法。这与明确排除 all 其他分支不同。例如,假设我们有一个部分看起来像这样的图:

       M   <-- origin/br2
      /
...--H   <-- origin/master, origin/br1
      \
       I--J   <-- br1
           \
            K--L   <-- br2 (HEAD)

进一步假设 br2 的上游是 origin/br2。要求 origin/br2..br2 中的提交(即 @{u}..HEAD)意味着您将 select 提交 LKJ 和 [=23] =].请求包含在 br2 没有其他分支 (即不是 br1)的提交将只得到 LK.如果您只需要 LK,那么您实际上需要枚举所有分支。

(枚举所有分支的技巧是使用 git for-each-refrefs/heads/ 前缀。如果您还应该考虑使用 git symbolic-ref 来读取当前分支名称将编写大量脚本或花哨的别名。这些命令 git for-each-refgit symbolic-ref 是 Git 调用的 plumbing 命令,意味着用于编写脚本和复杂的别名。与 git loggit diff 等 "user oriented" 命令相比,它们以更严格定义的、针对计算机使用的方式运行。调用那些 "user oriented" 有点可笑,但它们显然比 更面向用户 git diff-tree。)


1这里简化了一点。在查看多个分支名称的情况下,或者在合并提交到多个父分支之后,git log 必须以某种方式线性化图形拓扑。它通过优先级队列来实现,显示下一个 "highest priority" 提交并将该提交的父级添加到队列中。但是,对于简单的线性链,Git 通过历史向后移动的想法就足够了。