使用Git,在一个特定的分支上显示所有仅存在*的提交,而不是任何*其他

给定一个分支,我想看到在该分支上存在的提交列表。 在这个问题中,我们讨论如何查看哪个提交在一个分支上,而不是一个或多个指定的其他分支。

这有些不同。 我想看看哪一个提交是在一个分支上,而不是在其他分支上。

用例处于分支策略中,一些分支只能合并到一个分支,而不能直接提交。 这将用于检查是否有任何提交已经直接在“合并”分支上进行。

编辑:下面是设置一个虚拟的git回购testing的步骤:

git init echo foo1 >> foo.txt git add foo.txt git commit -am "initial valid commit" git checkout -b merge-only echo bar >> bar.txt git add bar.txt git commit -am "bad commit directly on merge-only" git checkout master echo foo2 >> foo.txt git commit -am "2nd valid commit on master" git checkout merge-only git merge master 

只有直接在合并分支上提交的消息“直接在合并上直接提交”才会出现。

我的同事刚刚发现这个优雅的解决schemegit log --first-parent --no-merges 。 在你的例子当然最初的提交仍然显示。

请阅读:这个答案不完全回答这个问题,因为最初的提交仍然显示。 另一方面,来到这里的许多人似乎find了他们正在寻找的答案。 请在投票前考虑这一点。 请参阅评论以供讨论。

致谢亲爱的朋友Redmumba :

 git log --no-merges origin/merge-only \ --not $(git for-each-ref --format="%(refname)" refs/remotes/origin | grep -Fv refs/remotes/origin/merge-only) 

origin/merge-only您的远程合并分支名称。 如果在一个仅限本地的git仓库上工作,用refs/heads代替refs/remotes/origin ,并用本地分支名称merge-onlyreplace远程分支名称origin/merge-only merge-only ,即:

 git log --no-merges merge-only \ --not $(git for-each-ref --format="%(refname)" refs/heads | grep -Fv refs/heads/merge-only) 

也许这可以帮助:

  git show-branch 

尝试这个:

 git rev-list --all --not $(git rev-list --all ^branch) 

基本上git rev-list --all ^branch得到的所有修订不在分支,然后你所有的修订在回购和减去以前的列表, 只是在分支的修订。

@布赖恩的评论之后:

从git rev-list的文档:

List commits that are reachable by following the parent links from the given commit(s)

所以一个像git rev-list A这样的命令,其中A是一个提交将列出可以从A到A的提交。

考虑到这一点,就像

git rev-list --all ^A

将列出不能从A到达的提交

所以git rev-list --all ^branch将列出所有不能从分支的顶端访问的提交。 这将删除分支中的所有提交,或者换言之,仅在其他分支中提交。

现在让我们来看看git rev-list --all --not $(git rev-list --all ^branch)

这将会像git rev-list --all --not {commits only in other branches}

所以我们想要列出all all commits only in other branches中不能从all commits only in other branches

哪些是仅在分支中提交的集合。 我们举一个简单的例子:

  master | A------------B \ \ C--------D--------E | branch 

这里的目标是得到D和E,这个提交不在任何其他分支。

git rev-list --all ^branch只给B

现在, git rev-list --all --not B不是git rev-list --all --not B就是我们想要的。 哪一个也是git rev-list -all ^B – 我们希望所有的提交都不能从B到达。在我们的例子中是D和E.这就是我们想要的。

希望这解释了命令如何正确工作。

评论后编辑:

 git init echo foo1 >> foo.txt git add foo.txt git commit -am "initial valid commit" git checkout -b merge-only echo bar >> bar.txt git add bar.txt git commit -am "bad commit directly on merge-only" git checkout master echo foo2 >> foo.txt git commit -am "2nd valid commit on master" 

经过上面的步骤,如果你做了一个git rev-list --all --not $(git rev-list --all ^merge-only)你将得到你正在寻找的提交 – "bad commit directly on merge-only"一个。

但是,一旦你在你的步骤做最后一步git merge master命令将不会给予预期的输出。 因为从现在开始,在合并中没有提交,因为在master中的一个额外的提交也被合并到合并。 所以git rev-list --all ^branch给出了空的结果,因此git rev-list -all --not $(git rev-list --all ^branch)将会给所有提交进行合并。

 git log origin/dev..HEAD 

这将显示你在你的分支所做的所有提交。

接受答案的另一个变种,与master一起使用

git log origin/master --not $(git branch -a | grep -Fv master)

筛选除主数据库之外的任何分支中发生的所有提交。

@Prakash答案的作品。 为了清楚起见…

 git checkout feature-branch git log master..HEAD 

列出function分支上的提交,但不包括上游分支(通常是您的主分支)。