Git run shell command for each commit
GitShellGit Problem Overview
I would like to walk through a range of commits and perform a shell command on each. If the command fails, I would like the walk to stop, otherwise keep going. I have looked at filter-branch
, but I don't want to re-write the commits, just check them out. for-each-ref
does not seem to allow you to specify a range to act on.
My specific problem is that I created a bunch of commits and I would like to ensure that each commit is buildable. I would like to do something like:
git foreach origin/master..master 'git submodule update && make clean && make'
I could of course write a shell script to do this, but it seems like the sort of thing that git might have a nice way to do.
Git Solutions
Solution 1 - Git
You can use interactive rebase with an exec option.
git rebase -i --exec <build command> <first sha you want to test>~
> --exec
Solution 2 - Git
You probably want rev-list.
#!/usr/bin/env bash
# test_commits.sh
while read -r rev; do
git checkout "$rev"
if ! git submodule update && make clean && make; then
>&2 echo "Commit $rev failed"
exit 1
fi
done < <(git rev-list "$1")
Then you can use it with
./test_commits.sh origin/master..master
Solution 3 - Git
Here's a cool one-liner using xargs
.
git rev-list @{upstream}..HEAD | xargs -n1 -I{} sh -c 'git checkout {} && git submodule update && make clean && make'
You may also want to pass the --reverse
option to rev-list so that the last checkout is HEAD.