So I've just learned that git rebase -i
allows users to merge individual commits in the middle of a branch's history. For that,
$ git rebase -i
This should bring a list of all commits in reverse order, similar to the one listed below:
pick 2361d4d implements something
pick a700451 fixes a bug
pick 79f9d04 fixes a bug again
pick 3172f07 implements some other thing
# Rebase 484d6d2..3172f07 onto 484d6d2 (4 commands)
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup [-C | -c] = like "squash" but keep only the previous
# commit's log message, unless -C is used, in which case
# keep only this commit's message; -c is same as -C but
# opens the editor
# x, exec = run command (the rest of the line) using shell
# b, break = stop here (continue rebase later with 'git rebase --continue')
# d, drop = remove commit
# l, label = label current HEAD with a name
# t, reset = reset HEAD to a label
# m, merge [-C | -c ] [# ]
It's possible to merge commit 79f9d04
with a700451
by updating the list of commands to set squash
instead of pick
in the commit you want to flatten onto the previous one, such as:
pick 2361d4d implements something
pick a700451 fixes a bug
squash 79f9d04 fixes a bug again
pick 3172f07 implements some other thing
(...)
Once we save the commit, Git opens an editor to rework the new commit message for the squashed commits, and you're set.
You can get git to do pretty much anything you want. You can even add completely unrelated or meaningless commits if you want. Git will happily let you fabricate any commit you want.
You can even split a monorepo into multiple repos and then merge them back, with no loss of history.
Git is incredibly powerful when you go beyond just the CLI. People complain a lot that the CLI is weird and unclear but when you understand what goes under the hood it makes complete sense.
The CLI is still pretty bad, and I say this as someone who's gotten so used to it that I find git GUIs more annoying than helpful.
log
gets a random flag fromdiff
,-p
, that's incredibly useful but buried in the documentation. Printing a readable graph log requires magic incantations that aren't worth memorizing.git branch
with no subcommand prints the list of branches, but to get similar behavior forgit remote
, you need to add-v
. Etc.