I'm trying to parse the output of commands run in a bash loop. Here is an example:

$ for i in `git log --format='%H'`; do echo $i ; git branch --contains $i; done | head -n 8
* foobar
* foobar
* foobar

The command git log --format='%H' prints out only the commit ID for each Git commit. The command git branch --contains $i prints out which Git branches contain the commit.

I'm trying to find the latest git commit that is not on branch 'foobar'. I would like to echo $i for the first branch whose output of git branch --contains $i contains a line that does not start with the * character, which specifies "current branch". What Bash documentation should I be reading?

Note that I am aware of other solutions to this problem. However, I plan on making additions that the other answers do not account for. Furthermore, this is how I improve my Bash scripting abilities.

  • You can achieve what you want in at least 2 ways - by grepping output of git branch --contains command or by checking how many lines this command returned with wc -l. In either way, you will likely need to use command substitution (you are already doing that but look up on differences between $() and backticks), [ command (type type [ and then help [), if or || or something similar, and break or exit to exit for loop. – Arkadiusz Drabczyk Jul 16 '14 at 10:27
  • @ArkadiuszDrabczyk: Thanks. With grep -v '^*' after the contains command I can get the name of the branch. Now, how might I output $i and break only when grep matches something? – dotancohen Jul 16 '14 at 11:20

Something like this might be what you want.

for i in $(git log --format='%H'); do
    branch="$(git branch --contains $i|awk 'NR==1{print $1}')"
    [ "$branch" != "*" ] && echo "commit '$i' is in branch '$branch'"

Prints the commit and its branch if not the current branch.

  • Thank you! I was not sure how to use the [[]] if in this context though I had found it used elsewhere online. The use of awk is creative. – dotancohen Jul 16 '14 at 12:18
  • No problem! The use of double braces here is actually not necessary, and it's a Bash only syntax that's only really required for using Bash regex =~ or glob comparisons against variables like case does with *. I've updated the post to use the single braces which makes it POSIX shell compliant. – John B Jul 16 '14 at 12:40
  • I see, thanks. I'm looking at some of your older posts as well to learn some Bash as you give excellent examples. Thank you! – dotancohen Jul 16 '14 at 12:43

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.