2

I want to (manually) merge changes in another branch into master. git diff --name-only gives me only all the files that are different. I don't want to merge a file that has a later commit in master (which most of the time means the file wasn't changed in the other branch).

For a file, how do I show which branch has a later commit? Basically I want to show the output of git log -1 somefile in two branches? Is there a way to avoid running the git log command twice, once for each branch?

Old Geezer
  • 14,854
  • 31
  • 111
  • 198
  • It's not clear to me whether you intend to run `git merge` here, but if you do, you don't get to control which files get merged: merge picks three commits, and uses those three inputs to diff *all* the files from the merge base to each branch tip, which means this kind of inspection isn't really going to help. (But if you're going to merge manually, or run `git merge-file` on specific files, see VonC's answer and my comment.) – torek Jun 09 '19 at 17:54

1 Answers1

2

You can try with the --all --branches log parameters:

git log -1 --all --branches -- yourFile

That will give you the most recent commit across all branches.

To limit that to only two branches, the --branches takes a shell glob pattern.
But that does not support an "or" in the pattern expression though. You might have to display the branch and grep for the ones you want.

As torek mentions in the comments, a revision range branch1...branch2 is also a simpler alternative.
That would be using the three dots notation, to target the set of commits that are reachable from either one of branch1 (left side) or branch2 (right side) but not from both.

So:

git log -1 branch1...branch2 -- yourFile

With Git 2.33 (Q3 2021), the notion of "revision range" is clarified:

See commit f302c1e (18 May 2021) by Junio C Hamano (gitster).
(Merged by Junio C Hamano -- gitster -- in commit b009fd4, 10 Jun 2021)

revisions(7): clarify that most commands take a single revision range

Sometimes new people are confused by how a revision "range" works, in that it is not a random collection of commits but a set of commits that are all connected to each other, and most Git commands work on a single such "range".

Give an example to clarify it.

revisions now includes in its man page:

There are several notations to specify a set of connected commits (called a "revision range"), illustrated below.

revisions now includes in its man page:

Commands that are specifically designed to take two distinct ranges (e.g. "git range-diff R1 R2" to compare two ranges) do exist, but they are exceptions.

Unless otherwise noted, all "git" commands that operate on a set of commits work on a single revision range. In other words, writing two "two-dot range notation" next to each other, e.g.

$ git log A..B C..D

does not specify two revision ranges for most commands. Instead it will name a single connected set of commits, i.e. those that are reachable from either B or D but are reachable from neither A or C. In a linear history like this:

---A---B---o---o---C---D

because A and B are reachable from C, the revision range specified by these two dotted ranges is a single commit D.

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    `--all` includes `--branches`: it's basically equivalent to `--branches --tags --remotes` except that it also includes things like `refs/stash` too (all refs). So OP probably wants just `--branches`, or in this case, `git log -1 branch1 branch2 -- yourfile`. – torek Jun 09 '19 at 17:52
  • @torek Did you meant `branch1...branch2`, as in https://git-scm.com/docs/gitrevisions#Documentation/gitrevisions.txt-Theem82308203emthree-dotSymmetricDifferenceNotation, meaning: " the set of commits that are reachable from either one of `branch1` (left side) or `branch2` (right side) but not from both"? – VonC Jun 09 '19 at 18:10
  • No, the idea here was to look at commits, newest-first (`git log`'s default sorting order when it has two commits to look at is by highest-committer-date) until one of them meets the `-- yourFile` criterion, then show that one commit and quit. However, the three-dot notation would be even more useful if you want to show *nothing* if the file isn't changed since common starting commits. (or in other words, your improvement of my improvement is (I think) an improvement :-) ) – torek Jun 09 '19 at 18:21
  • @torek OK. Improvement FTW! – VonC Jun 09 '19 at 18:29
  • Thanks. I have a question about the output. I find that when the latest is in a branch other than master, the branch name is shown in color after the commit id. When the latest is in master, no branch name is indicated. It's the same whether I use `master...b2` or `b2...master`. Is this how it is supposed to work? – Old Geezer Jun 10 '19 at 03:17
  • @OldGeezer `master...b2` or `rb2...master` will return indeed the same set of commits. To avoid the branch name in color being added, use the `---no-decorate` option – VonC Jun 10 '19 at 05:07