简体   繁体   中英

How do I get the information about each branch of my git local repository

This is what git branch -v produces in one of my local directories

* develop e229f7a Merge branch 'develop' of https://github.com/me/myremote-repo.git into develop Some diffs
  master  3343dea [behind 2] Added git-log, same as git_log without colorization

I am attempting to go through the set of branches and the output from that command and if the output contains [ahead n] or [behind m], I want to put out a statement like:

[behind 2] --> bin [master] 3343dea
[ahead 1]  --> bin [develop] 99345b

for each branch IF it contains ahead or behind.

I currently have the following in my code:

MOD=`git branch -v | perl -wlne '/^..(\S+)\s+([a-f0-9]+)\s+(\[ahead\s+\d+\]|\[behind\s+\d+\])/ or next; print  "$3 --> $ENV{reponame} [$1] $2"; '`;

    [ ! -z "$MOD" ] &&  MOD="$MOD" | ok=false
    if $ok; then
        echo " OK --> $reponame [$br]"
    else
       # a series of UGLY HACKs to get pretty-printing
       MOD=`echo "$MOD" | tr -d '\011\012\015' | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//'` | sed -e 's/]#/]\
 #/'
       if [ ! -z "$MOD" ]; then
          echo -e " $MOD" && continue
       fi
    fi


 bin [develop] --> Out of sync with origin/HEAD at /Users/me/bin
 bin [develop] --> Changes to be staged/committed at /Users/me/bin
 [behind 2] --> bin [master] 3343dea
 OK --> patti [develop]
 OK --> notes [master]
 OK --> indecks [develop]
 OK --> queue [develop]
 OK --> frameworks [develop]
 OK --> nodejs [master]
 OK --> perl-forth [develop]
 OK --> patti [master]
 OK --> blog [develop]

The problem is that I only get the first one. If there are two branches with either a ahead or behind I only get the first one. I've tried several ways to get the output from git branch -v into an array and then iterate through the array and if it matches the pattern, do the print. The problem is that I can't find a way to get the output into the array in a way that works. When I then iterate through the array, I get a list of all the files.

I use:

branches={`git branch -v`)
for i in "${branches[@]}"
do
    echo "$i"
done

What I get is the list of all the files in the directory!

Why, and what should I do?

Use read in a while loop to get the lines from perl into MOD one by one.

git branch -v |
perl -wlne'
   print "$3 --> $ENV{reponame} [$1] $2"
      if /^..(\S+)\s+([a-f0-9]+)\s+(\[(?:ahead|behind)\s+\d+\])/
' |
while IFS= read -r MOD; do
   printf '{%s}\n' "$MOD"  # Replace with code that uses $MOD
done

I think you can get most of the way there without perl or awk by specifying the format for the git branch output . Note that $REPONAME is interpolated by the shell because I'm using a double-quoted string. The stuff in %(...) is part of the git formatting:

$ export REPONAME=bin
$ git branch --format "%(upstream:track) --> $REPONAME [%(refname:short)] %(objectname:short=6)" | grep '^\['
[behind 15] --> bin [master] 5b1e08

I didn't work very hard on that to get rid of lines where the branch is up-to-date, so I punted to grep .

$ git branch --format "%(upstream:track) --> $REPONAME [%(refname:short)] %(objectname:short=6)"
  --> bin [a] 5b1e08
  --> bin [briandfoy/how-to-install-perl] 1d7456
[behind 15] --> bin [master] 5b1e08

You can add logic, but I didn't get it to the point of not outputting blank lines:

$ git branch --format "%(if)%(upstream:track)%(then)%(upstream:track) --> $REPONAME [%(refname:short)] %(objectname:short=6)%(else)%(end)"


[behind 15] --> bin [master] 5b1e08

But, I think in your comment to ikegami you wanted to have up-to-date branches have "OK". Modify the if-then-else to cover just the first column and always output the rest:

$ git branch --format "%(if)%(upstream:track)%(then)%(upstream:track)%(else)OK%(end) --> $REPONAME [%(refname:short)] %(objectname:short=6)"
OK --> bin [a] 5b1e08
OK --> bin [briandfoy/some_feature] 1d7456
[behind 15] --> bin [master] 5b1e08

If you want some other string for the out of sync branches, just change that branch of the if-then-else :

$ git branch --format "%(if)%(upstream:track)%(then)Out of sync%(else)OK%(end) --> $REPONAME [%(refname:short)] %(objectname:short=6)"
OK --> bin [a] 5b1e08
OK --> bin [briandfoy/some_feature] 1d7456
Out of sync --> bin [master] 5b1e08

You can put the entire format into its own variable, but you need to be careful with that because it interpolates the $REPONAME . You'll have to set the $FORMAT per repo. I think this is a little easier to digest:

$ export FORMAT="%(if)%(upstream:track)%(then)%(upstream:track)%(else)OK%(end) --> $REPONAME [%(refname:short)] %(objectname:short=6)"
$ git branch --format "$FORMAT"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM