Automating Git tasks is not about hooks or aliases, that’s a story for another day.
Let’s imagine for a second that you are a lazy person, not too lazy, but lazy enough to get a little upset every time you need to, let’s say, update your beautiful working repository or even cheat on your SEO configuration by mentioning ‘Automating’ out of nowhere (see what I did here?). You can’t mess it up, because you and your team are so proud of the beautiful branching model you achieved and you treat merge commits as if they were bitten by a zombie.
But, of course, to achieve that ‘Good Practices of the Month’ badge and be delighted with the output of your git log you need to do some tricky stuff on a daily basis.
Let’s continue with our imagination exercise, and imagine this workflow:
- You work in a feature branch for every story
- That branch is checked out from ‘develop’
- All the commits created in the feature branch must be taken to ‘develop’ at the time they’re created
- Obviously, those commits, need to be synched with the ‘upstream’ and ‘origin’ remotes
- Once that feature branch is done it is merged with a third one, ‘staging’, ‘qa’, ‘release’, whatever
- You hate, absolutely hate, merge commits
So, that comes with some tricky implications: if you don’t want merges in your ‘develop’ branch, and don’t want to get the ‘develop’ commits to the feature (since they might have zero relation with your work) you’ll need to git rebase your changes from the feature to ‘develop’ instead of just merging it.
That means, for example, we need to:
git fetch upstream
git merge-base develop upstream/develop
git reset --hard <SHA-returned-by-the last command>
git merge upstream/develop
That’s four commands every time you want to get the latest changes.
Remember: You are lazy.
But wait! There’s hope, because, in case you didn’t notice: git is awesome.
So, here’s the thing, git has this awesome feature, where you can write a script, add it to your PATH and make git to run it. Just like that.
First, you need a file named ‘git-whatever’ it doesn’t need an extension, and must be named with the ‘git-’ prefix.
I recommend to place it inside an specific folder and add the folder to the PATH, since you may want to store many files in there.
So, what’s inside the file? Well, it must begin with the address of the interpreter for the scripting language you’ll use. Just a hint: the git installation folder comes with an sh interpreter for free!
#!/bin/sh // That’s the generic route for git’s own sh interpreter
After that, you just can do whatever you want, assign variables, control the execution flow, iterate and the most important thing: set the git commands you need to run every time.
Here’s an example for a script that helps automating the job described above, fetches the upstream remote, finds the newest common commit, resets to that point and merges from there:
branch_name=$(git branch | sed -n -e 's/^\* \(.*\)/\1/p')
echo "Current branch is $branch_name"
echo "Fetching upstream..."
git fetch upstream
echo "Getting the common ancestor with the remote..."
common_ancestor=$(git merge-base $branch_name upstream/$branch_name)
echo "Resetting your branch to the best merging point..."
git reset --hard $common_ancestor
echo "Merging your remote branch..."
git merge upstream/$branch_name
echo "All done!"
Now, all you need to do is go to your repo and ‘git whatever’.