问题描述:

If I create a commit with Git, it provides a simple log message with the branch name, short SHA and a one line description:

[branchname 481f23b] Fixes from code review

But if I use git log --oneline, I only get short SHAs and subjects:

481f23b Fixes from code review

bb4070e Merge branch 'update-docs' into 'master'

e0095b2 Merge remote-tracking branch 'origin/master' into HEAD

I can't work out any way to use git log --format="format:..." to print out the current branch name on every line.

For example, if I use --format="format:[%D %h] %s":

[HEAD -> branchname, origin/branchname 481f23b] Fixes from code review

[ bb4070e] Merge branch 'update-docs' into 'master'

[ e0095b2] Merge remote-tracking branch 'origin/master' into HEAD

Is there any way to configure git log to display the (current) branch name on every log line?

网友答案:

With a bit of shell hackery, it seems I can emulate this with sed and bash substitution:

git log -200 --format="format:%Cgreen[BRANCHNAME %h]%Creset %s" | (sed "s/BRANCHNAME/$(git symbolic-ref -q --short HEAD || git describe --tags --exact-match)/")

Of course, this will display every single commit is now "part" of this branch, even if it wasn't originally.

网友答案:

Your shell trick will work, though I'd simply get the branch name first (into a shell variable) and then use that directly in the --format line.

There's a good reason git doesn't do this, though: commits are not so much "on a branch" as "contained in some set of branches". For instance:

...--o--A--B--C     <-- branch1
      \
       D--E         <-- branch2

Obviously commits A through C are "on" branch1 and D and E are "on" branch2. But then let's do a git merge branch2 while we're on branch1:

...--o--A--B--C     <-- branch1
      \        \
       D--E-----M   <-- branch2

Now commits A through C are on branch2, too.

Now let's use git branch -d branch1 to remove the label branch1, which is safe since it's merged into branch2:

...--o--A--B--C
      \        \
       D--E-----M   <-- branch2

Nothing has changed, but now A through C are only "on" branch2 since branch1 is gone.

The commit graph is fixed (because commits are, in a fairly deep sense, their SHA-1s: if you change anything, including parent IDs, commit messages, or timestamps, you get a new, different commit, even if the source tree attached to that commit is the same). The branch labels, though, are ephemeral: they move, change, or even disappear entirely, without changing the graph.

In any case, a single commit can be "on" more than one branch. Any given branch label points to a single commit, but that commit can point back to multiple previous commits. A merge commit is defined as a commit pointing to at least two parents, and as such it causes those commits to be contained within the branch, even when—as is normal during development—at least some of those commits have another label pointing to them, or pointing to something that points to them.

You don't even need merges to get this effect: just create a new branch that points to some existing commit. For instance, before deleting branch1, even before merging, create a new label branch3 also pointing to commit C:

...--o--A--B--C     <-- branch1, branch3
      \
       D--E         <-- branch2

Now commits A through C are on two branches, and when you merge branch1 into branch3, they'll be on three branches.

相关阅读:
Top