我想列出只是特定分支的一部分的所有提交。

使用下面的代码,它列出了来自分支的所有提交,也包括来自父(master)的所有提交

git log mybranch

我发现的另一种选择是排除主可达的提交,并给我我想要的,但我想避免知道其他分支名称的需要。

git log mybranch --not master

我试图使用git for-each-ref,但它也列出了mybranch,所以实际上它排除了所有:

git log mybranch --not $(git for-each-ref --format '^%(refname:short)' refs/heads/)

更新:

我正在测试一个我不久前发现的新选项,直到现在看来,这可能是我一直在寻找的:

git log --walk-reflogs mybranch

更新(2013 - 02 - 13 t15:08):

——walk-reflogs选项很好,但我检查了reflogs的过期时间(默认90天,gc.reflogExpire)。

我想我找到了我一直在寻找的答案

git log mybranch --not $(git for-each-ref --format='%(refname)' refs/heads/ | grep -v "refs/heads/mybranch")

我只是从可用的分支列表中删除当前分支,并使用该列表从日志中排除。这样我只能得到只有mybranch才能到达的提交。


当前回答

你可以尝试这样做:

#!/bin/bash

all_but()
{
    target="$(git rev-parse $1)"
    echo "$target --not"
    git for-each-ref --shell --format="ref=%(refname)" refs/heads | \
    while read entry
    do
        eval "$entry"

        test "$ref" != "$target" && echo "$ref"
    done
}

git log $(all_but $1)

或者,借用Git用户手册中的食谱:

#!/bin/bash
git log $1 --not $( git show-ref --heads | cut -d' ' -f2 | grep -v "^$1" )

其他回答

我发现这种方法相对简单。

结帐到分行和比

运行 -2 HEAD . git

这将只提供两个sha:

1)分支的最后一次提交[C1]

2)和提交父分支的第一次提交[C2]

现在运行 git log——decoration——pretty=oneline——reverse——name-status <C2>..<C1> .

这里C1和C2是运行第一个命令时将得到的两个字符串。在第二个命令中输入这些不包含<>的值。

这将给出分支内文件更改历史的列表。

在这里,我根据Richard Hansen的回答(和Ben C的建议)给出了一个别名,但我对其进行了调整,以排除标签。别名应该相当健壮。

# For Git 1.22+
git config --global alias.only '!b=${1:-$(git branch --show-current)}; git log --oneline --graph "heads/$b" --not --exclude="$b" --branches --remotes #'
# For older Git:
git config --global alias.only '!b=${1:-$(git symbolic-ref -q --short HEAD)}; b=${b##heads/}; git log --oneline --graph "heads/$b" --not --exclude="$b" --branches --remotes #'

使用示例:

git only mybranch  # Show commits that are in mybranch ONLY
git only           # Show commits that are ONLY in current branch

注意,ONLY表示如果删除给定的分支(不包括标记的影响),提交将被丢失(在垃圾收集之后)。即使有一个名为mybranch的标记(多亏了前缀heads/),别名也应该工作。还要注意,根据ONLY的定义,如果提交是任何远程分支(包括上游分支)的一部分,则不会显示提交。

别名将单行历史记录显示为所选提交的图形。

  a --- b --- c --- master
   \           \
    \           d
     \           \
      e --- f --- g --- mybranch (HEAD)
       \
        h --- origin/other

对于上面的例子,git只会显示:

  * (mybranch,HEAD)
  * g
  |\
  | * d
  * f 

为了包含标签(但仍然不包括HEAD),别名变成(针对旧Git进行如上调整):

git config --global alias.only '!b=${1:-$(git branch --show-current)};  git log --oneline --graph --all --not --exclude="refs/heads/$b" --exclude=HEAD --all #'

或者包含所有标签的变体,包括HEAD(并默认删除当前分支,因为它不会输出任何东西):

git config --global alias.only '!git log --oneline --graph --all --not --exclude=\"refs/heads/$1\" --all #'

最后一个版本是唯一真正满足commit -that-are-lost-if-given-branch-is-deleted标准的版本,因为如果签出分支就不能删除分支,HEAD或任何其他标记指出的提交都不会丢失。然而,前两个变体更有用。

最后,别名不能用于远程分支(例如。Git只有origin/master)。别名必须修改,例如:

git config --global alias.remote-only '!git log --oneline --graph "$1" --not --exclude="$1" --remotes --branches #'

这个问题在2021年还在讨论,8年前就被问到了。我很困惑为什么没有人建议git -first parent。这难道不是现今的解决方案吗?我目前也有同样的问题,这看起来对我来说很好。我综合了这些选项:

git --first-parent --cherry  first-commit-on-branch..

我甚至从master中合并了更多的提交到我的特性分支中,但这些提交被过滤掉了,因为cherry是-cherry-pick, -right-only和-no-merges的组合。 您需要手动查找分支上的第一次提交,或者从那时起查找所有后续提交。

我通过使用git log <branch>来做到这一点 还有一个选项是——not <branch-name> 原始文档:git-log

格式示例:

git log branch-name  --date-order --format='%ai %an <%ae> %h %f'--format='%ai , %an ,<%ae> ,%h ,%f' >> c:\log.csv

我做了一个别名,以便能够简单地输入“git logbranch”,并有特定于当前分支的所有提交。 这是别名:

[alias]
    logbranch = "!cd -- \"${GIT_PREFIX:-.}\" && CURRENT_BRANCH=$(git branch --show-current) && git log $CURRENT_BRANCH --not $(git for-each-ref --format='%(refname)' refs/heads/ | grep -v refs/heads/$CURRENT_BRANCH) #"

注意:把它放在主目录下的.gitconfig文件的[alias]标签下。

因此,我基本上使用了最初在问题帖子中发布的内容,并使用CURRENT_BRANCH变量使其更快。 希望这将节省你一些时间!