Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Git status over all repo's

Tags:

git

status

What tools, if any, are available to show the status of my git repo's and how much they are forward/behind versus their remotes? I'm imagining something like this exists:

repo1 +2 <--> remote1
repo1    <--> remote1 +3
repo2    <--> remote +10

First row shows repo1 is ahead 2 commits, second show remote2 is ahead with 3 commits, third show only remote of repo2 is ahead of 10 commits.

like image 979
Ruud Poutsma Avatar asked Sep 12 '13 07:09

Ruud Poutsma


3 Answers

You can find several scripts, all based on looking for .git folder:

  • git-multi-status.sh
  • find-dirty.sh
  • GitStatus (python)
  • Other options, as suggested in "Git Status Across Multiple Repositories on a Mac"
  • ...

The first one can be adapted to display the kind of status you are after:

#!/bin/bash

# usage: $0 source_dir [source_dir] ...
# where source_dir args are directories containing git repositories

red="\033[00;31m"
green="\033[00;32m"
yellow="\033[00;33m"
blue="\033[00;34m"
purple="\033[00;35m"
cyan="\033[00;36m"

reset="\033[00m"


if [ $# -eq 0 ] ; then
  ARGS=( "foldername" "foldername/subfoldername" )
else
  ARGS=$@
fi

for i in ${ARGS[@]} ; do
  for gitdir in `find $i -name .git` ; do
    ( working=$(dirname $gitdir)
      cd $working
      RES=$(git status | grep -E '^# (Changes|Untracked|Your branch)')
      STAT=""
      grep -e 'Untracked' <<<${RES} >/dev/null 2>&1
      if [ $? -eq 0 ] ; then
        STAT=" $red[Untracked]$reset"
      fi
      grep -e 'Changes not staged for commit' <<<${RES} >/dev/null 2>&1
      if [ $? -eq 0 ] ; then
        STAT="$STAT $red[Modified]$reset"
      fi
      grep -e 'Changes to be committed' <<<${RES} >/dev/null 2>&1
      if [ $? -eq 0 ] ; then
        STAT="$STAT $green[Staged]$reset"
      fi
      grep -e 'Your branch is ahead' <<<${RES} >/dev/null 2>&1
      if [ $? -eq 0 ] ; then
        STAT="$STAT $yellow[Unpushed]$reset"
      fi
      grep -e 'Your branch is behind' <<<${RES} >/dev/null 2>&1
      if [ $? -eq 0 ] ; then
        STAT="$STAT $cyan[Unmerged]$reset"
      fi

      if [ -n "$STAT" ] ; then
        echo -e "$working :$STAT"
      fi
    )
  done
done
like image 23
VonC Avatar answered Nov 18 '22 04:11

VonC


I'm not entirely sure what it means to say that one repo is ahead or behind another repo. They are just sets, and without any sort of reference, there is no ordering. You could say that the local repo has commits that the remote one doesn't. But you can't say whether it's ahead or behind without talking about branches. You might be able to say whether a repo is up-to-date or not though.

Also, when communicating with a remote, the local git client has no idea how many commits are in-between the local branch tip and the remote one. It won't know that until the data has been transferred locally.

What you can do instead, is run git fetch --all, and have a script like this (I called it `git-repo-status locally):

#!/bin/bash

# Taken from http://stackoverflow.com/questions/620650/can-i-easily-update-all-local-git-branches-from-remote-branches-simultaneously/answer-9076361
# tweaked by me to help give status of local versus upstream branches.
main() {
  REMOTES="$@";
  if [ -z "$REMOTES" ]; then
    REMOTES=$(git remote);
  fi
  REMOTES=$(echo "$REMOTES" | xargs -n1 echo)
  echo "$REMOTES" | while read REMOTE; do
    git remote show $REMOTE -n \
    | awk '/merges with remote/{print $5" "$1}' \
    | while read line; do
      RB=$(echo "$line"|cut -f1 -d" ");
      ARB="refs/remotes/$REMOTE/$RB";
      LB=$(echo "$line"|cut -f2 -d" ");
      ALB="refs/heads/$LB";

      # This is in reference to the local branch.
      NBEHIND=$(( $(git rev-list --count $ALB..$ARB 2>/dev/null) +0));
      NAHEAD=$(( $(git rev-list --count $ARB..$ALB 2>/dev/null) +0));

      if [ "$NBEHIND" -gt 0 -a "$NAHEAD" -gt 0 ]; then
        echo "$LB <--> $REMOTE/$RB: -$NBEHIND +$NAHEAD";
      elif [ "$NBEHIND" -gt 0 ]; then
        echo "$LB <--> $REMOTE/$RB: -$NBEHIND";
      elif [ "$NAHEAD" -gt 0 ]; then
        echo "$LB <--> $REMOTE/$RB: +$NAHEAD";
      fi
    done
  done
}

main $@

Running it produces something like:

:: git repo-status
master <--> upstream/master: -14

I realize it's not a direct answer to your issue, but I don't think what you want is possible without running git fetch --all and grabbing the revisions from upstream. If you're willing to do that, then the above may be useful to you.

like image 102
John Szakmeister Avatar answered Nov 18 '22 02:11

John Szakmeister


I'm aware that this question is not that fresh anymore but I've written an open-source tool for exactly that reason: It finds local git repositories and tracks their state showing the current branch and a status string for all your local repositories in one place.

  • https://github.com/awaescher/RepoZ

This makes it a perfect starting place for all your (git) development tasks as well.

RepoZ

If you are using Windows, you might enjoy an additional effect:

Because with git you usually don't have dedicated branch folders like MyTool\trunk\... or MyTool\v2.0\... you can't see in which branch you are actively working in when using the Windows File Explorer.

So the cool thing about that tool is that while running, it will automatically enhance all File Explorer windows by adding the current branch and the status string of the repository opened in the File Explorer window (if any).

enter image description here

It's 100% open source, so please give it a try and I would be very happy if you'd feel comfortable to contribute.

Update

RepoZ now comes with a command line enhancement called grr which makes use of the aggregated repository information from RepoZ to show live data in the command line plus the possibility to jump from repository to repository with the cd command: grr cd RepoZ

enter image description here

like image 2
Waescher Avatar answered Nov 18 '22 03:11

Waescher