The letter A styled as Alchemists logo. lchemists
Published May 25, 2020 Updated June 14, 2020

Git Rebase Exec

Demonstrates how to interactively rebase while executing commands.


# Hello and welcome to the Alchemists Screencasts!
# Today, we'll look at Git Rebase Exec.

# Exec is the most flexible and powerful of the rebase commands.
# It is also the most complex. 😅
# Let's begin by studying our Git history:

gl master..calc

# 💡 For details on the `gl` alias see the *Git Log Pretty* screencast.

# As you can see, we have a couple of commits on our `calc` branch.
# Let's rebase and see what *exec* can do for us:

git rebase --interactive

# Notice, during the rebase, Git printed the script being executed.
# Then, directly after, we saw the output of our script: "Test."
# Also, I'm using "x" instead of "exec" to type less.
# 💡 See the *Git Rebase Abbreviations* screencast for details.

# Put another way, Git Rebase Exec is excellent at rebase automation.
# If your script's exit code isn't an error, then the rebase will continue.
# Otherwise, the rebase will hault so you can manually address issues.
# Let's facilitate a situation in which the rebase will fail:

git rebase --interactive

# As you can see, the rebase halted because script execution failed.
# Normally, we'd take corrective action.
# We'll continue since we manufactured the error:

git rebase --continue

# So far we've only run a single script but we can customize further:

git rebase --interactive

# As you can see, we ran different scripts for different commits.
# Typing out individual scripts can be cumbersome, though.
# Luckily, Git allows us to point to custom scripts for improved reuse:

printf "%s\n" "#! /usr/bin/env bash" > bin/rubocop-scan
printf "\n%s\n" 'rubocop "$(git diff --name-only HEAD^)"' >> bin/rubocop-scan
chmod 755 bin/rubocop-scan

# The script above is more complicated, so let's break it down from right to left:
# First, we use Git Diff to list files changed between previous and current commit:

git diff --name-only HEAD^

# Second, we give the file to Rubocop for scanning:

rubocop lib/tutorial/calc.rb

# With the script understood, let's rebase with it:

git rebase --interactive

# Ah, Rubocop detected a flaw in the first commit that we can fix:

vi lib/tutorial/calc.rb

git add lib/tutorial/calc.rb
git commit --amend --no-edit
git rebase --continue

# We've got a conflict due to the change in the previous commit.
# No problem, we'll fix that too:

vi lib/tutorial/calc.rb

git add lib/tutorial/calc.rb
git rebase --continue

# Great, our commits are properly styled now. 😉
# We could have easily run tests for each commit too.
# I encourage you to explore further. 🚀

# Before wrapping up, it's worth mentioning rebase accepts the `--exec` option:

git rebase --interactive --exec bin/rubocop-scan

# The above is great when applying the same script to *all* commits.
# If you don't need the visual confirmation, the following is faster:

GIT_EDITOR=true git rebase --interactive --exec bin/rubocop-scan

# 💡 Use of `GIT_EDITOR=true` tricks Git into thinking the editor saved successfully.

# Enjoy!
# ☿ 🜔 🜍 🜂 🜃 🜁 🜄