74

Given a project with several local branches, each tracking some remote branch, is there a command that lists all branches that have unpushed commits? (That is, even if none of those branches are checked out.)

I don't want to see the commits themselves, nor do I want to see branches that are up-to-date, I just want to see which branches are ahead of their remotes.

I have tried git log --branches --not --remotes --simplify-by-decoration --decorate --oneline, but it doesn't seem to show what I need. Running it on my current repo gives no output, but running git status on my current branch shows Your branch is ahead of 'origin/branchname' by 2 commits.

git for-each-ref --format="%(refname:short) %(push:track)" refs/heads and git branch -v both show branches that are up to date as well as ones that need pushing. However, they do both show my current branch as [ahead 2].

Other commands I have found eg. git log @{u}.., git cherry -v list the commits themselves, not the branches.

Side question: why would the output from git log --branches --not --remotes --simplify-by-decoration --decorate --oneline not include branches that git branch -v shows as ahead? Isn't the former command just looking at which refs/heads do not correspond to a known remote; so wouldn't a branch listed as [ahead 2] meet this criteria?

detly
  • 29,332
  • 18
  • 93
  • 152
  • 1
    Possible duplicate of [Show git ahead and behind info for all branches, including remotes](http://stackoverflow.com/questions/7773939/show-git-ahead-and-behind-info-for-all-branches-including-remotes) – Tim Biegeleisen Aug 30 '16 at 07:06
  • @TimBiegeleisen Interesting, but the accepted answer is a Bash script (I use Linux/OSX/Windows), and the other answer gives nearly empty output. – detly Aug 30 '16 at 07:12
  • 1
    @TimBiegeleisen Okay, I've identified the problem and this is indeed a duplicate. – detly Aug 30 '16 at 07:14
  • 1
    I felt that the effort needed to give you a high quality answer would far exceed doing a thorough search here on SO and elsewhere. – Tim Biegeleisen Aug 30 '16 at 07:16
  • 1
    @TimBiegeleisen Hah, I've been searching all day for this, and I didn't think to use the terms "ahead" and "behind" (or "track" etc.)! – detly Aug 30 '16 at 07:18
  • @TimBiegeleisen Okay, upon reflection, it's not a duplicate. I'm also completely puzzled as to *why* there'd be a difference between what `branch -v` tells me vs. `log --branches --not --remotes --simplify-by-decoration --decorate`. – detly Aug 30 '16 at 23:15
  • Might it make a difference that the branch where my `log` command doesn't work as expected is only ahead due to merge commits? – detly Aug 31 '16 at 00:02

4 Answers4

104

The --no-walk option to log seems to do a better job of what I need than --simplify-by-decoration. My full command is:

git log --branches --not --remotes --no-walk --decorate --oneline

...which I've aliased to unpushed.

detly
  • 29,332
  • 18
  • 93
  • 152
14
git for-each-ref --format="%(refname:short) %(push:track)" refs/heads

That remain the most precise answer that you can easily parse/grep to get the desired output (like removing up-to-date branches)

You can do so in a bash script that you will call git-xxx (no extension), somewhere in your $PATH or %PATH%.
That script can then be called with git xxx, and will use git bash.
That is portable and will work across platforms (meaning even on Windows, where <Git For Windows>/usr/bin includes 200+ linux commands (grep, sed, awk, xargs, ...)

VonC
  • 1,262,500
  • 529
  • 4,410
  • 5,250
  • 1
    Note that this doesn't highlight branches that are not tracking a remote (and which therefore have all unpushed commits). – Tamlyn Jan 09 '18 at 14:12
  • 1
    @Tamlyn I agree. In the context of this question however, I focused only on local branches which have set a remote tracking branch. – VonC Jan 09 '18 at 14:23
7

although the answers above are very helpful and show alot of data but for others coming here looking for a solution to find local branches which are ahead i.e. have not been pushed yet. can get the exact list by executing:

git branch -v | grep ahead
Zain Baloch
  • 410
  • 5
  • 9
  • Not sure if this works reliably... I just tried it after a commit (no push) to an existing branch and no `ahead` text appears in the `git branch -v` command. This is with Git version `git version 2.24.3 (Apple Git-128)`. It did, however, work with an older Git version, `git version 2.13.0.windows.1` – Jason Capriotti Apr 23 '21 at 18:18
  • I should also mention the test that did work on the older Git version was for a branch that existed on the remote and had a local un-pushed commit. However, it does not work for branches that do not exist on the remote (but I'm not sure if OP was asking about that scenario or not). – Jason Capriotti Apr 23 '21 at 18:21
  • I modified it to find all branches out of sync with this: `git branch -v |grep 'ahead\|behind'` – Martin P. Jun 30 '22 at 19:05
  • This does not show branches with no upstream at all, which could be a significant gotcha... It also doesn't work if the terminal language is not English. – Emil Styrke Jun 20 '23 at 06:59
5

You can also see what branches are not yet merged to master

git checkout master

and then

git branch --no-merged
Danon
  • 2,771
  • 27
  • 37
  • You can seemingly do this without checking out the branch first: "With --merged, only branches merged into the named commit (i.e. the branches whose tip commits are reachable from the named commit) will be listed. With --no-merged only branches not merged into the named commit will be listed. If the argument is missing it defaults to HEAD (i.e. the tip of the current branch)." https://git-scm.com/docs/git-branch – Glenn 'devalias' Grant Jul 08 '21 at 03:58