Git - Programatically determine if local commits have not been pushed

Viewed 817

I've seen lots of posts/answers on how to display all of the local commits for all local branches that have not been commited.

I have a narrow use case, and have not found an answer.

I need to determine, from within a bash script, if my CURRENT branch has commits that have not been pushed upstream to the same branch. A count would be fine, but I really just need to know if a push has not yet been done. I don't care about any branches except the current branch, and in this case I've already checked to see if the branch is local (i.e. has not yet set upstream origin).

Mainly, I don't want the commits printed out, I just want to know that the number of unpushed commits is > 0.

3 Answers

The upstream of the current branch is @{u}. @ is a synonym for HEAD.

@..@{u} selects the commits which are upstream, but not local. If there are any you are behind. We can count them with git rev-list.

# Move 4 commits behind upstream.
$ git reset --hard @{u}^^^

$ git rev-list @..@{u} --count
4

@{u}..@ does the opposite. It selects commits which are local but not upstream.

# Move to upstream
$ git reset --hard @{u}

# Add a commit
$ git commit --allow-empty -m 'test'
[main 6dcf66bda1] test

$ git rev-list @{u}..@ --count
1

And if both are 0 you are up to date.

Note: this will only be "up to date" as of your last fetch. Whether you want to combine this with a fetch is up to you, but one should get used to the fact that Git does not regularly talk to the network.

(I've borrowed from ElpieKay's answer).

See gitrevisions for more about @, .. and many ways to select revisions.

Suppose the branch is foo.

git fetch origin foo
git rev-list FETCH_HEAD..foo --count

The 1st command gets the latest head of the foo in the remote repository and stores its commit sha1 in FETCH_HEAD.

git rev-list returns a number. If it's 0, all commits of the foo in the local repository have been included in the foo branch in the remote repository. If it's larger than 0, there are this number of commits not included in the remote foo yet.

Being included is different from being pushed if the procedure involves a pending change like a pull request or a merge request. The commands can determine if the local branch's commits have been merged to(included in) its remote counterpart.

You're looking for git status. It will give you output like:

On branch main
Your branch is ahead of 'origin/main' by 1 commit.
(use "git push" to publish your local commits)

nothing to commit, working tree clean

And you can grep for this with:

git status | grep -E "Your branch is ahead of '.*' by ([0-9]*) commit."
Related