Git只能获得特定分支的提交日志
我想列出只是特定分支的一部分的所有提交。
通过以下内容,它列出了来自分支的所有提交,还列出了来自父(主)
git log mybranch
我发现的另一个select是排除主人可达的提交,并给我我想要的,但是我想避免需要知道其他分支的名字。
git log mybranch --not master
我试图使用git for-each-ref
,但它也列出mybranch,所以实际上它是排除所有:
git log mybranch --not $(git for-each-ref --format '^%(refname:short)' refs/heads/)
更新:
我正在testing一个新的选项,我刚才发现,直到现在看来,这可能是我所期待的:
git log --walk-reflogs mybranch
更新(2013-02-13T15:08):
–walk-reflogs选项很好,但是我检查了reflog的过期(默认90天, gc.reflogExpire )。
我想我find了我正在寻找的答案:
git log mybranch --not $(git for-each-ref --format='%(refname)' refs/heads/ | grep -v "refs/heads/mybranch")
我只是从可用分支列表中删除当前分支,并使用该列表从日志中排除。 这样我只能得到只有mybranch才能达到的提交 。
从听起来你应该使用cherry
:
git cherry -v develop mybranch
这将显示mybranch中包含的所有提交,但不在 开发中 。 如果你离开最后一个选项( mybranch ),它会比较当前的分支。
正如VonC所指出的那样,你总是把你的分支与另一个分支进行比较,所以知道你的分支,然后select与哪个分支进行比较。
但是我想避免需要知道其他分支的名字。
我不认为这是可能的:在Git中的一个分支总是基于另一个或至less在另一个提交,如“ git diff不够显示 ”所解释的:
你需要一个参考点为你的日志显示正确的提交。
正如“ GIT – 我从哪里分支? ”中提到的那样 :
分支只是指向DAG中某些提交的指针
所以,即使git log master..mybranch
是一个答案,它仍然会显示太多的提交,如果mybranch
是基于myotherbranch
,本身是基于master
。
为了find这个引用(你的分支的起源),你只能parsing提交,看看它们在哪个分支,如下所示:
- “ Git:find一个提交来自哪个分支 ”。
- “ 我怎么能看到另一个分支是从哪个分支分出来的呢?
我终于find了做OP的想法。 这很简单:
git log --graph [branchname]
该命令将以graphics的格式显示从提供的分支可达的所有提交。 但是,通过查看其中*
是提交行中第一个字符的提交图,您可以轻松地过滤该分支上的所有提交。
例如,我们来看下面的cakephp GitHub git log --graph master
中git log --graph master
的摘录:
D:\Web Folder\cakephp>git log --graph master * commit 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4 |\ Merge: c3f45e8 0459a35 | | Author: José Lorenzo Rodríguez <lorenzo@users.noreply.github.com> | | Date: Tue Aug 30 08:01:59 2016 +0200 | | | | Merge pull request #9367 from cakephp/fewer-allocations | | | | Do fewer allocations for simple default values. | | | * commit 0459a35689fec80bd8dca41e31d244a126d9e15e | | Author: Mark Story <mark@mark-story.com> | | Date: Mon Aug 29 22:21:16 2016 -0400 | | | | The action should only be defaulted when there are no patterns | | | | Only default the action name when there is no default & no pattern | | defined. | | | * commit 80c123b9dbd1c1b3301ec1270adc6c07824aeb5c | | Author: Mark Story <mark@mark-story.com> | | Date: Sun Aug 28 22:35:20 2016 -0400 | | | | Do fewer allocations for simple default values. | | | | Don't allocate arrays when we are only assigning a single array key | | value. | | * | commit c3f45e811e4b49fe27624b57c3eb8f4721a4323b |\ \ Merge: 10e5734 43178fd | |/ Author: Mark Story <mark@mark-story.com> |/| Date: Mon Aug 29 22:15:30 2016 -0400 | | | | Merge pull request #9322 from cakephp/add-email-assertions | | | | Add email assertions trait | | | * commit 43178fd55d7ef9a42706279fa275bb783063cf34 | | Author: Jad Bitar <jadbitar@mac.com> | | Date: Mon Aug 29 17:43:29 2016 -0400 | | | | Fix `@since` in new files docblocks | |
正如你所看到的,只有提交8314c2ff833280bbc7102cb6d4fcf62240cd3ac4
和c3f45e811e4b49fe27624b57c3eb8f4721a4323b
的*
是提交行中的第一个字符。 这些提交来自主分支,而其他四个来自其他分支。
下面的shell命令应该做你想做的事情:
git log --all --not $(git rev-list --no-walk --exclude=refs/heads/mybranch --all)
注意事项
如果你有mybranch
签出,上述命令将无法正常工作。 这是因为mybranch
上的提交也可以通过HEAD
访问,所以Git并不认为提交对mybranch
是唯一的。 为了在mybranch
签出时能够工作,还必须为HEAD
添加一个排除:
git log --all --not $(git rev-list --no-walk \ --exclude=refs/heads/mybranch \ --exclude=HEAD \ --all)
但是,除非mybranch
被检出,否则你不应该排除HEAD
,否则你冒着显示不是mybranch
专有的提交的风险。
同样,如果你有一个名为origin/mybranch
的远程分支对应于本地的mybranch
分支,你必须排除它:
git log --all --not $(git rev-list --no-walk \ --exclude=refs/heads/mybranch \ --exclude=refs/remotes/origin/mybranch \ --all)
如果远程分支是远程仓库的默认分支(通常只适用于origin/master
),你还必须排除origin/HEAD
:
git log --all --not $(git rev-list --no-walk \ --exclude=refs/heads/mybranch \ --exclude=refs/remotes/origin/mybranch \ --exclude=refs/remotes/origin/HEAD \ --all)
如果你有分支签出, 并有一个远程分支,远程分支是远程存储库的默认分支,那么你最终排除很多:
git log --all --not $(git rev-list --no-walk \ --exclude=refs/heads/mybranch \ --exclude=HEAD --exclude=refs/remotes/origin/mybranch \ --exclude=refs/remotes/origin/HEAD \ --all)
说明
git rev-list
命令是一个低级别(pipe道)命令,用于遍历给定的修订版本并转储遇到的SHA1标识符。 把它看作等同于git log
除了它只显示SHA1-没有日志消息,没有作者的名字,没有时间戳,没有那些“奇特”的东西。
顾名思义, --no-walk
选项阻止了git rev-list
走向血统链。 所以,如果你inputgit rev-list --no-walk mybranch
,它将只打印一个SHA1标识符: mybranch
分支的提示提交的mybranch
。
--exclude=refs/heads/mybranch --all
参数告诉git rev-list
从每个引用开始,除了refs/heads/mybranch
。
所以,当你运行git rev-list --no-walk --exclude=refs/heads/mybranch --all
,Git将打印除refs/heads/mybranch
之外的每个ref的提示提交的SHA1标识符。 这些提交和他们的祖先是你不感兴趣的提交 – 这些是你不想看到的提交。
其他的提交是你想看到的,所以我们收集git rev-list --no-walk --exclude=refs/heads/mybranch --all
的输出git rev-list --no-walk --exclude=refs/heads/mybranch --all
并告诉Git显示除了那些提交和它们的祖先以外的所有内容。
--no-walk
参数对于大型版本库是必要的(对于小型版本库是一个优化):没有它,Git将不得不打印,而且shell必须收集(并且在内存中存储)更多的提交标识符。 对于大型的存储库,收集的提交数量可能会轻易超过shell的命令行参数限制。
Git的bug?
我会期待以下工作:
git log --all --not --exclude=refs/heads/mybranch --all
但事实并非如此。 我猜这是Git中的一个bug,但也许是故意的。
快速回答:
git log $(git merge-base master b2)..HEAD
我们说:
-
你有一个主分支
-
做一些提交
-
您创build了一个名为b2的分支
-
做
git log -n1
; 提交ID是b2和master之间的合并基础 -
在b2中做一些提交
-
git log
会显示你的b2和master的日志历史logging -
使用提交范围,如果你不熟悉这个概念,我邀请你去谷歌它或堆栈溢出它,
对于你的实际情况,你可以做例如
git log commitID_FOO..comitID_BAR
“..”是日志命令的范围运算符。
这意味着,在一个简单的forms,给我所有日志比commitID_FOO更近
-
看第4点,合并基地
所以:
git log COMMITID_mergeBASE..HEAD
会显示你的差异 -
Git可以像这样检索合并基础
git merge-base b2 master
-
最后你可以这样做:
git log $(git merge-base master b2)..HEAD
你可以尝试这样的事情:
#!/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" )
在我的情况下,我们正在使用Git Flow和GitHub。 所有你需要做的是:在GitHub上比较你的function分支和开发分支。
它将显示仅提交给您的function分支的提交。
例如:
https://github.com/your_repo/compare/develop…feature_branch_name
这将输出当前分支上的提交。 如果有任何parameter passing,它只是输出散列。
git_show_all_commits_only_on_this_branch
BRANCH=$(git branch | grep "*" | awk '{print $2}') OUT=$(git cherry -v master $BRANCH ) if [ -z "$1" ] then echo "$OUT" else echo "$OUT" | awk '{print $2}' fi