The following examples only deal with a single repository. Use a loop in a surrounding script to run them on multiple repositories.
You will probably want to run (e.g.) git fetch origin
to update your local remote-tracking branches before using the following commands (so that you are checking against the most up-to-date tips of the upstream branches).
If you are only concerned with the branch that is currently checked out:
git status -sb
If the first line reports “ahead”, then the current branch has commits that are not part of its upstream branch. The output of this command is not suitable for consumption directly by a program (it is a “porcelain” command). For programatic consumption use a “plumbing” command to list the “ahead” commits:
git rev-list HEAD@{upstream}..HEAD
You can pipe that to wc -l
to get a count. If you are only interested in the “ahead” status (not the exact count), then test -n "$(git rev-list -n 1 HEAD@{upstream}..HEAD)"
may be faster.
If you want to check on all the branches of a repository:
git branch -v
Again, you will see “ahead” for branches with commits that are not part of their upstream branch. This is also a “porcelain” command, so if you want to reliably detect the state in a program, then you will want to use some “plumbing” commands:
git for-each-ref --shell --format='
b=%(refname:short)
u=${b}'@{upstream}'
if git rev-parse --verify --quiet "$u" >/dev/null 2>&1; then
test -n "$(git rev-list -n 1 "$u..$b")" &&
echo "$b: has unpushed commits"
else
echo "$b: no upstream configuration" >&2
fi
' refs/heads | sh
Adjust the echo
statements (or replace them with other commands) to suit your purposes.
$ git log origin/master..master fatal: ambiguous argument 'origin/master..master': unknown revision or path not in the working tree. Use '--' to separate paths from revisions
– Pretoria