Git 日志以获取仅针对特定分支的提交

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/14848274/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-10 15:30:18  来源:igfitidea点击:

Git log to get commits only for a specific branch

git

提问by dimirc

I want to list all commits that are only part of a specific branch.

我想列出所有仅属于特定分支的提交。

With the following, it lists all the commits from the branch, but also from the parent (master)

通过以下内容,它列出了来自分支的所有提交,以及来自父(主)的提交

git log mybranch

The other option I found, was to exclude the commits reachable by master and gives me what I want, BUT I would like to avoid the need of knowing the other branches names.

我发现的另一个选项是排除 master 可以访问的提交并给我我想要的东西,但我想避免知道其他分支名称的需要。

git log mybranch --not master

I was trying to use git for-each-ref, but it is also listing mybranch so actually it is excluding all:

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

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

Update:

更新:

I'm testing a new option that I found a while ago, and till now seems that this could be what I was looking for:

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

git log --walk-reflogs mybranch

Update (2013-02-13T15:08):

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

The --walk-reflogs option is good, but I checked that there is an expiration for reflogs (default 90 days, gc.reflogExpire).

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

I think I found the answer I was looking for:

我想我找到了我正在寻找的答案:

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

I'm just removing the current branch from list of branches available and using that list to be excluded from the log. This way I only get the commits that are only reached by mybranch.

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

回答by Smilie

From what it sounds like you should be using cherry:

从听起来你应该使用cherry

git cherry -v develop mybranch

This would show all of the commits which are contained within mybranch, but NOT in develop. If you leave off the last option (mybranch), it will compare the current branch instead.

这将显示包含在mybranch 中的所有提交,但不包含在develop 中。如果您不使用最后一个选项 ( mybranch),它将改为比较当前分支。

As VonC pointed out, you are ALWAYS comparing your branch to another branch, so know your branches and then choose which one to compare to.

正如 VonC 指出的那样,您总是将您的分支与另一个分支进行比较,因此请了解您的分支,然后选择要比较的分支。

回答by VonC

BUT I would like to avoid the need of knowing the other branches names.

但我想避免知道其他分支名称的需要。

I don't think this is possible: a branch in Git is always based on another one or at least on another commit, as explained in "git diff doesn't show enough":

我认为这是不可能的:Git 中的一个分支总是基于另一个或至少基于另一个提交,如“ git diff 显示不够”中所述:

enter image description here

在此处输入图片说明

You need a reference point for your log to show the right commits.

您需要一个日志参考点来显示正确的提交。

As mentioned in "GIT - Where did I branch from?":

如“ GIT - 我从哪里分支?”中所述:

branches are simply pointers to certain commits in a DAG

分支只是指向 DAG 中某些提交的指针

So even if git log master..mybranchis one answer, it would still show too many commits, if mybranchis based on myotherbranch, itself based on master.

所以即使git log master..mybranch是一个答案,它仍然会显示太多提交,如果mybranch基于myotherbranch,本身基于master

In order to find that reference (the origin of your branch), you can only parse commits and see in which branch they are, as seen in:

为了找到该引用(您的分支的来源),您只能解析提交并查看它们在哪个分支中,如下所示:

回答by Lukman

I finally found the way to do what the OP wanted. It's as simple as:

我终于找到了做 OP 想要做的事情的方法。这很简单:

git log --graph [branchname]

The command will display all commits that are reachable from the provided branch in the format of graph. But, you can easily filter all commits on that branch by looking at the commits graph whose *is the first character in the commit line.

该命令将以图形格式显示从提供的分支可访问的所有提交。但是,您可以通过查看*提交行中第一个字符的提交图来轻松过滤该分支上的所有提交。

For example, let's look at the excerpt of git log --graph masteron cakephp GitHub repo below:

例如,让我们看看git log --graph master下面 on cakephp GitHub repo的摘录:

D:\Web Folder\cakephp>git log --graph master
*   commit 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4
|\  Merge: c3f45e8 0459a35
| | Author: José Lorenzo Rodríguez <[email protected]>
| | 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 <[email protected]>
| | 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 <[email protected]>
| | 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 <[email protected]>
|/|   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 <[email protected]>
| | Date:   Mon Aug 29 17:43:29 2016 -0400
| |
| |     Fix `@since` in new files docblocks
| |

As you can see, only commits 8314c2ff833280bbc7102cb6d4fcf62240cd3ac4and c3f45e811e4b49fe27624b57c3eb8f4721a4323bhave the *being the first character in the commit lines. Those commits are from the master branch while the other four are from some other branches.

如您所见,仅提交8314c2ff833280bbc7102cb6d4fcf62240cd3ac4c3f45e811e4b49fe27624b57c3eb8f4721a4323b具有*提交行中的第一个字符。这些提交来自 master 分支,而其他四个来自其他一些分支。

回答by Richard Hansen

The following shell command should do what you want:

以下 shell 命令应该执行您想要的操作:

git log --all --not $(git rev-list --no-walk --exclude=refs/heads/mybranch --all)

Caveats

注意事项

If you have mybranchchecked out, the above command won't work. That's because the commits on mybranchare also reachable by HEAD, so Git doesn't consider the commits to be unique to mybranch. To get it to work when mybranchis checked out, you must also add an exclude for HEAD:

如果您已mybranch签出,则上述命令将不起作用。那是因为 上的提交mybranch也可由 访问HEAD,因此 Git 不认为提交是mybranch. 要在mybranch检出时使其正常工作,您还必须为HEAD以下项添加排除项:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=HEAD \
    --all)

However, you should notexclude HEADunless the mybranchis checked out, otherwise you risk showing commits that are not exclusive to mybranch.

然而,你应该排除HEAD,除非mybranch被检查出来,否则你可能会显示出并不互斥提交mybranch

Similarly, if you have a remote branch named origin/mybranchthat corresponds to the local mybranchbranch, you'll have to exclude it:

同样,如果您有一个origin/mybranch与本地mybranch分支相对应的远程分支,则必须将其排除:

git log --all --not $(git rev-list --no-walk \
    --exclude=refs/heads/mybranch \
    --exclude=refs/remotes/origin/mybranch \
    --all)

And if the remote branch is the default branch for the remote repository (usually only true for origin/master), you'll have to exclude origin/HEADas well:

如果远程分支是远程存储库的默认分支(通常仅适用于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)

If you have the branch checked out, andthere's a remote branch, andthe remote branch is the default for the remote repository, then you end up excluding a lot:

如果您已签出分支,并且有一个远程分支,并且远程分支是远程存储库的默认分支,那么您最终会排除很多:

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)

Explanation

解释

The git rev-listcommand is a low-level (plumbing) command that walks the given revisions and dumps the SHA1 identifiers encountered. Think of it as equivalent to git logexcept it only shows the SHA1—no log message, no author name, no timestamp, none of that "fancy" stuff.

git rev-list命令是一个低级(管道)命令,它遍历给定的修订并转储遇到的 SHA1 标识符。把它想象成等价于git log除了它只显示 SHA1——没有日志消息,没有作者姓名,没有时间戳,没有那些“花哨”的东西。

The --no-walkoption, as the name implies, prevents git rev-listfrom walking the ancestry chain. So if you type git rev-list --no-walk mybranchit will only print one SHA1 identifier: the identifier of the tip commit of the mybranchbranch.

--no-walk顾名思义,该选项可防止git rev-list走祖先链。所以如果你输入git rev-list --no-walk mybranch它只会打印一个 SHA1 标识符:mybranch分支的提示提交的标识符。

The --exclude=refs/heads/mybranch --allarguments tell git rev-listto start from each reference except for refs/heads/mybranch.

--exclude=refs/heads/mybranch --all参数告诉git rev-list从除了每个参考启动refs/heads/mybranch

So, when you run git rev-list --no-walk --exclude=refs/heads/mybranch --all, Git prints the SHA1 identifier of the tip commit of each ref except for refs/heads/mybranch. These commits and their ancestors are the commits you are notinterested in—these are the commits you do notwant to see.

因此,当您运行 时git rev-list --no-walk --exclude=refs/heads/mybranch --all,Git 会打印每个引用的提示提交的 SHA1 标识符,除了refs/heads/mybranch. 这些提交和他们的祖先是您在提交中,这些都是你的兴趣提交希望看到的。

The othercommits are the ones you want to see, so we collect the output of git rev-list --no-walk --exclude=refs/heads/mybranch --alland tell Git to show everything but those commits and their ancestors.

其他的提交是你想看到的,所以我们收集的输出的东西git rev-list --no-walk --exclude=refs/heads/mybranch --all,并让Git显示一切,但这些提交和他们的祖先。

The --no-walkargument is necessary for large repositories (and is an optimization for small repositories): Without it, Git would have to print, and the shell would have to collect (and store in memory) many more commit identifiers than necessary. With a large repository, the number of collected commits could easily exceed the shell's command-line argument limit.

--no-walk参数对于大型存储库是必需的(并且是对小型存储库的优化):没有它,Git 将不得不打印,并且 shell 将不得不收集(并存储在内存中)比必要的更多的提交标识符。对于大型存储库,收集的提交数量很容易超过 shell 的命令行参数限制。

Git bug?

吉特错误?

I would have expected the following to work:

我本来希望以下内容起作用:

git log --all --not --exclude=refs/heads/mybranch --all

but it does not. I'm guessing this is a bug in Git, but maybe it's intentional.

但事实并非如此。我猜这是 Git 中的一个错误,但也许是故意的。

回答by Frederic Nault

Fast answer:

快速回答:

git log $(git merge-base master b2)..HEAD

Let's say:

让我们说:

  1. That you have a masterbranch

  2. Do a few commits

  3. You created a branch named b2

  4. Do git log -n1; the commit Id is the merge base between b2 and master

  5. Do a few commits in b2

  6. git logwill show your log history of b2 and master

  7. Use commit range, if you aren't familiar with the concept, I invite you to google it or stack overflow-it,

    For your actual context, you can do for example

    git log commitID_FOO..comitID_BAR
    

    The ".." is the range operator for the log command.

    That mean, in a simple form, give me all logs more recent than commitID_FOO...

  8. Look at point #4, the merge base

    So: git log COMMITID_mergeBASE..HEADwill show you the difference

  9. Git can retrieve the merge base for you like this

    git merge-base b2 master
    
  10. Finally you can do:

    git log $(git merge-base master b2)..HEAD
    
  1. 你有一个分支

  2. 做一些提交

  3. 您创建了一个名为b2的分支

  4. git log -n1; 提交 ID 是 b2 和 master 之间的合并基础

  5. b2 中做一些提交

  6. git log将显示您的 b2 和 master 的日志历史记录

  7. 使用commit range,如果你不熟悉这个概念,我请你google一下或者stackoverflow-it,

    对于您的实际上下文,您可以执行例如

    git log commitID_FOO..comitID_BAR
    

    “..”是日志命令的范围运算符。

    这意味着,以简单的形式,给我所有比 commitID_FOO 更新的日志......

  8. 看点#4,合并基础

    所以:git log COMMITID_mergeBASE..HEAD会告诉你区别

  9. Git可以像这样为你检索合并基础

    git merge-base b2 master
    
  10. 最后你可以这样做:

    git log $(git merge-base master b2)..HEAD
    

回答by Brad Parks

This will output the commits on the current branch. If any argument is passed, it just outputs the hashes.

这将输出当前分支上的提交。如果传递了任何参数,它只会输出哈希值。

git_show_all_commits_only_on_this_branch

git_show_all_commits_only_on_this_branch

#!/bin/bash
function show_help()
{
  ME=$(basename 
#!/bin/bash

all_but()
{
    target="$(git rev-parse )"
    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 )
) IT=$(cat <<EOF usage: $ME {NEWER_BRANCH} {OLDER_BRANCH} {VERBOSE} Compares 2 different branches, and lists the commits found only in the first branch (newest branch). e.g. $ME -> default. compares current branch to master $ME B1 -> compares branch B1 to master $ME B1 B2 -> compares branch B1 to B2 $ME B1 B2 V -> compares branch B1 to B2, and displays commit messages ) echo "$IT" exit } if [ "" == "help" ] then show_help fi # Show commit msgs if any arg passed for arg 3 if [ "" ] then OPT="-v" fi # get branch names OLDER_BRANCH=${2:-"master"} if [ -z "" ] then NEWER_BRANCH=$(git rev-parse --abbrev-ref HEAD) else NEWER_BRANCH= fi if [ "$NEWER_BRANCH" == "$OLDER_BRANCH" ] then echo " Please supply 2 different branches to compare!" show_help fi OUT=$(\git cherry $OPT $OLDER_BRANCH $NEWER_BRANCH) if [ -z "$OUT" ] then echo "No differences found. The branches $NEWER_BRANCH and $OLDER_BRANCH are in sync." exit; fi if [ "$OPT" == "-v" ] then echo "$OUT" else echo "$OUT" | awk '{print }' fi

回答by John Szakmeister

You could try something like this:

你可以尝试这样的事情:

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

Or, borrowing from the recipe in the Git User's Manual:

或者,借用Git 用户手册中配方

git rev-list --exclude=master --branches --no-walk

回答by jthill

git rev-list master --not $(git rev-list --exclude=master --branches --no-walk)

will list the tips of every branch that isn't master.

将列出每个不是的分支的提示master

git shortlog --no-merges --graph --abbrev-commit master..<mybranch>

will list every commit in master's history that's not in any other branch's history.

将列出master在任何其他分支的历史记录中没有的历史记录中的每个提交。

Sequencing is important for the options that set up the filter pipeline for commit selection, so --brancheshas to follow any exclusion patterns it's supposed to apply, and --no-walkhas to follow the filters supplying commits rev-list isn't supposed to walk.

排序对于为提交选择设置过滤器管道的选项很重要,因此--branches必须遵循它应该应用的任何排除模式,并且--no-walk必须遵循提供提交 rev-list 不应该走的过滤器。

回答by Alex

I'm using the following commands:

我正在使用以下命令:

git log --no-merges --graph --oneline --decorate master..<mybranch>

or

或者

git rev-list --simplify-by-decoration -2 HEAD

回答by Mustkeem K

I found this approach relatively easy.

我发现这种方法相对容易。

Checkout to the branch and than

结帐到分行,然后

  1. Run

    git rev-list --simplify-by-decoration -2 HEAD
    
  1. git log --decorate --pretty=oneline --reverse --name-status <C2>..<C1>
    

This will provide just two SHAs:

这将仅提供两个 SHA:

1) last commit of the branch [C1]

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

2) and commit parent to the first commit of the branch [C2]

2) 并将父级提交到分支的第一次提交 [C2]

  1. Now run

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

    ##代码##

Here C1 and C2 are two strings you will get when you run first command. Put these values without <> in second command.

这里 C1 和 C2 是你运行第一个命令时会得到的两个字符串。将这些值不带 <> 放在第二个命令中。

This will give list of history of file changing within the branch.

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