Skip to content

Instantly share code, notes, and snippets.

@debugloop
Last active July 31, 2026 10:45
Show Gist options
  • Select an option

  • Save debugloop/a2f6eda9c306526c26800e79e822a22e to your computer and use it in GitHub Desktop.

Select an option

Save debugloop/a2f6eda9c306526c26800e79e822a22e to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
export DIR=$(mktemp -d)
cd $DIR
git init
git config commit.gpgsign false
git config user.name Someone
git config user.email someone@example.com
export GIT_AUTHOR_DATE="2000-01-01T12:34:56"
export GIT_COMMITTER_DATE="2000-01-01T12:34:56"
echo -e 'change M1\n' > foo
git add foo
git commit -m 'root, change M1'
echo -e 'change M2\n' >> foo && git commit -am 'change M2'
git switch -c feature-a
echo -e 'change A1\n' >> foo && git commit -am 'change A1'
echo -e 'change A2\n' >> foo && git commit -am 'change A2'
echo -e 'change A3\n' >> foo && git commit -am 'change A3'
git switch main
echo -e 'change M3\n' >> foo && git commit -am 'change M3'
git switch feature-a
echo
git log --oneline --graph --all
echo
echo Agenda:
echo 1. stacked branches
echo 2. absorb and interactive rebase
echo 3. upstream rebase
echo 4. update and push stack
echo
exec $SHELL
echo "Exited interactive shell. If you did not intend to do this you can go into the
test repo using the current shell with:
cd $DIR"
# 1. stacked branches
# * git branch -f pr-1 @~~
# * git branch -f pr-2 @~
# * git log --oneline --graph --all
# 2. absorb and interactive rebase
# * make changes
# * git add and absorb
# * git rebase --autosquash --interactive --keep-base main
# 3. upstream rebase
# * git rebase --update-refs main
# 4. update and push stack
# * git log --pretty='format:%D' main.. | cut -d' ' -f3
# * git log --pretty='format:%D' main.. | cut -d' ' -f3 | xargs git push --set-upstream --force-with-lease --force-if-includes origin
# 5. [bonus] git trim
@debugloop

Copy link
Copy Markdown
Author

Execute the script to start the demo. Presenter's notes are the comment at the bottom and map onto the printed instructions.

Important message to get across: Set appropriate defaults for these flags in gitconfig, and otherwise create some aliases.

@debugloop

Copy link
Copy Markdown
Author

The mentioned git absorb tool (automatic fixup generation).

Aliases for step 4:

# to tell if its master/main reliably
main = "!f() {if git remote | grep -qE '.+'; then git symbolic-ref refs/remotes/origin/HEAD --short | cut -d/ -f2; else echo main fi}; f"
# force push whole stack, I only ever use this to push
puf = "!git stack | xargs git push --set-upstream --force-with-lease --force-if-includes origin"
# prints the current stack
stack = "!git for-each-ref --format='%(refname:short)' refs/heads/ --merged HEAD --no-merged $(git main) --sort=committerdate"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment