Therefore, I have accumulated a few git config and commands to help with these workflows.git rebase help page, it is a very good documentation piece that I recommend you to read top to bottom one day.
Here are useful git config flags and commands that solves common situations.
Avoid adding flags that are almost always used.
git config --global rebase.updateRefs true
git config --global rebase.rescheduleFailedExec true
git config --global rebase.rebaseMerges no-rebase-cousins
git config --global rebase.autoStash true
git config --global rebase.autoSquash true
# bonus
git config --global commit.verbose true
They can still be disabled with --no-flag, for example --no-update-refs
The default flags of rebase are conservative, but I found that the optional rebase algorithms/heuristics to be predictable enough that I was always using them.
So to avoid having to specify them over and over, I put them in options:
git rebase --interactive will automatically call git rebase --edit-todo before starting the rebase.
pick deadbee The oneline of this commitpick fa1afe1 The oneline of the nextcommit. . .
It is just an ordered list of \(command \)commit-sha $some-description-that-will be-ignored :
git rebase will stop if a commit fails to apply. When you are done editing and/or resolving conflicts you can continue with git rebase --continue.
if you have a history like this:
X
\
A---M---B
/
---o---O---P---origin/master
Suppose you want to rebase the side branch starting at A onto origin/master . Make sure that the current HEAD is B , and call
git rebase -i -r --onto origin/master O
pick deadbee Implement feature XXX
fixup f1a5c00 Fix to feature XXX
exec make
pick c0ffeee The oneline of the nextcommit
edit deadbab The oneline of the commit after
exec cd subdir; make test
If it stops at some point, you can continue with git rebase --continue.
You may want to check that your history editing did not break anything by running a test, or at least recompiling at intermediate points in history by using the “exec” command (shortcut “x”). You may do so by creating a todo list like this one.
The interactive rebase will stop when a command fails (i.e. exits with non-0 status) to give you an opportunity to fix the problem. You can continue with git rebase --continue.
$ git rebase -ix "make" origin/master
This command lets you check that intermediate commits compile correctly. The todo list becomes like that:
pick 5928aea one
exec "make"
pick 04d0fda two
exec "make"
git add fileA.txt
git commit -m "A"
git add fileB.txt
git commit -m "B"
echo "lorem ipsum" >> fileA.txt
git add fileA.txt
git commit --fixup COMMIT-SHA
You can continue working as long as needed. Eventually then, you can rebase all the changes and the TODO will automatically contain fixup todos.
git rebase -i origin/master
Also, if you want to modify the commit log message you can:
# This will modify the content, and replace the commit log message
git commit --fixup=amend:COMMIT-SHA
# that will only replace the commit log message
git commit --fixup=reword:COMMIT-SHA
# ( ^ means parent )
git rebase -i COMMIT-TO-SPLIT-SHA^
# mark the commit to split with the action “edit”
git reset HEAD^
git add foo.c bar.h
git commit -m "the appropriate message"
# repeat last two steps until working tree is clean
git rebase --continue
This commit is largely inspired from the git rebase documentation. Let us imagine a branch called matthieutalbot-cmake , that contains a commit modifying some tls support (unrelated to cmake). First, we create the needed branch
$ git checkout -b matthieutalbot-tlsv1.3&& git checkout -
then rebase todo will look like
label onto
reset onto
pick 192837Switch fromGNU Makefiles to CMake
pick 5a6c7eDocument the switch to CMake
pick 918273Fix detection of OpenSSL inCMake
pick afbecd http: add support forTLS v1.3
pick fdbaec Fix detection of cURL inCMake on Windows
update-ref refs/heads/matthieutalbot-tlsv1.3
and you can make it look like that
label onto
reset onto
pick afbecd http: add support forTLS v1.3
update-ref refs/heads/mtt-tlsv1.3
pick 192837Switch fromGNU Makefiles to CMake
pick 5a6c7eDocument the switch to CMake
pick 918273Fix detection of OpenSSL inCMake
pick fdbaec Fix detection of cURL inCMake on Windows
The one commit in this list that is not related to CMake may very well have been motivated by working on fixing all those bugs introduced by switching to CMake, but it addresses a different concern. To split this branch into two topic branches, the todo list could be edited like this.
label/reset/merge instructions are explained in the --rebase-merges documentation: in contrast to a regular interactive rebase, there are label, reset and merge commands in addition to pick ones.
The label command associates a label with the current HEAD when that command is executed. (These labels are created as worktree-local refs (refs/rewritten/<label>) that will be deleted when the rebase finishes. That way, rebase operations in multiple worktrees linked to the same repository do not interfere with one another. )
The reset command resets the HEAD, index and worktree to the specified revision. It is similar to an exec git reset --hard <label>, but refuses to overwrite untracked files.
When the -C is changed to a lower-case -c, the message will be opened in an editor after a successful merge so that the user can edit the message.
Failed label , reset and merge commands are always rescheduled.
By using some convention for branch naming, you can then use this snipped (if I prepend all my branches with matthieutalbot-)
$ cat >> $HOME/.bashrc <<'HERE_DOC'
function gpushforce (){
git branch --list'matthieutalbot-*'--format='%(refname:lstrip=2)'|
xargs -t git push --force-with-lease origin}
HERE_DOC
By using the same convention for branch naming as gpushforce (see above)
$ cat >> $HOME/.bashrc <<'HERE_DOC'
function gfetchforce (){
echo "Careful not to loose any local commits!"
git branch --list ${BRANCH_PREFIX}* --format='+%(refname:lstrip=2):%(refname:lstrip=2)' |
git fetch origin --verbose --update-head-ok --stdin
HERE_DOC