How to (recursively) find/identify git repositoris with unpushed commits

Issue

I use tons of separate git repositories to organize my work (>30) in a well-organized folder structure with a single root. Since I work on >= 2 computers I always must make sure that all changes are pushed before I leave my office.

To identify all repositories with files which have been:

  • changed/added/deleted/etc (i.e. they files are already under version control) or
  • not tracked yet (i.e., new files which git doesn’t know yet what to do with)

… I use the following convenient one-liner (without I could not do my work anymore):

find . -name ‘.git’ | while read repo ; do repo=${repo//.git/}; git
-C "$repo" status -s | grep -q -v "^$" && echo -e "\n\033[1m${repo}\033[m" && git -C "$repo" status -s || true; done

(written by hoijui, posted here). Of course I define an alias for it (which I call gitstatus) that I can execute before I leave my office.

This awesome script has sadly one single disadvantage: It can’t identify repositories in which I have committed files that I forgot to push. The reason is that the script checks for files with a certain status, but in this case there are no such files. Instead I need to search for an output message of the form:

  • "Your branch is ahead of ‘origin/master’ by 1 commit." or
  • "Your branch is ahead of ‘origin/master’ by 2 commits."
  • (Or values >2. I just added both messages to emphasize that these messages have slightly different strings for n=1 and n>1 commits.)

I assume that this is a trivial task for anybody who has written a few bash scripts in the past. I however already struggle reading the script above without investing >1 hour… Also, I was surprised to not have found any similar script on stackoverflow — even the above-mentioned (incredibly useful) script was not posted here before! (As far as I can tell.) Thus, although I’m technically asking for help here, I thought that even the question itself (due to the script above) might already be helpful to many! 🙂 And the improved script (if anybody provides an answer) would hopefully be even more helpful.

Anyway, thank you!

Just FYI: The dual (complement) to this question is how to find/identify repositories in which I have remote (rather than local) changes. You find it here.

Solution

Found the solution! It was on Stackoverflow after all… (Don’t know why I didn’t find it initially.)

Anyway, here a function that one can simply add to the .bashrc:

function gitStatus()
{
echo "Repositories with unpushed commits:"
find . -type d -iname '.git' -exec sh -c 'cd "${0}/../" && git status | grep -q "is ahead of" && pwd' "{}" \;
echo ""
echo "Repositories with changed/deleted/added/untracked files:"
find . -name '.git' | while read repo ; do repo=${repo//.git/}; git -C "$repo" status -s | grep -q -v "^$" && echo -e "\n\033[1m${repo}\033[m" && git -C "$repo" status -s || true; done
}

Note that:

  • the first "find script" is the actual answer.
  • the second "find script" is the one I already posted in the question itself, which lists all changes/added/deleted/untracked files.
  • there’s a minor inconsistency between the both scripts: The first reports absolute paths, the second relative ones. (But that hardly matters, so I didn’t care making this consistent.)

The solution was provided by ‘Qetesh’ in Stackoverlow’s post on
Git – How to find all "unpushed" commits for all projects in a directory? Note that there are other solutions in that thread; but this one seems to most elegant to me.

Answered By – Prof.Chaos

This Answer collected from stackoverflow, is licensed under cc by-sa 2.5 , cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply

(*) Required, Your email will not be published