Painless Linear History in Git

by Paweł Lipski @plipski

git rebase --onto

P

Specify:

  • place onto which the commits are going to be rebased (new-base)
  • beginning of the rebased part of history (from-exclusive)
  • the branch to rebase = also the end of the rebased history
git rebase --onto <new-base> <from-exclusive> <rebased-branch>

git rebase --interactive

P

Useful even when no squash/reword/edit is going to happen,

just so that you can inspect and/or abort the planned rebase

git push --force-with-lease

P

Local:
feature/foo
Local mirror of remote:
origin/feature/foo
Remote:
feature/foo
Before a push commit Z commit Y commit X
After a successful push commit Z commit Z commit Z

git push: only push if X is an ancestor of Z

(i.e. no commit can be "removed" from the remote by a push)

 

git push --force: push no matter what

 

git push --force-with-lease: only push if Y==X

(i.e. local mirror is up to date with remote)

Fast-forward

P

In gitspeak,  to fast-forward a branch means to update the branch pointer in such a way that its new pointed commit is a direct descendant of the prior pointed commit.

 

In other words, the new commit is a child, or grandchild, or grandgrandchild, ... of the old commit.

git merge --ff-only

P

  • won't update the current branch unless the merged branch is a direct descendant of the current branch
  • won't ever create a merge commit (a one with 2+ parents)

git pull --ff-only

P

Does git fetch, then tries to fast-forward the local branch to match its remote tracking branch.

 

If the newly-fetched remote diverged from the local branch (e.g. because it has been rebased before being pushed), then it rejects to update the local branch.

 

No unexpected merges like in the regular "git pull".

git reset --keep

P

HEAD (current commit) working directory
git reset [--mixed] X Move to X No change
git reset --keep X Move to X Exactly as in X

Aborts if any uncommitted change would be overwritten
git reset --hard X Move to X Exactly as in X

Uncommitted changes are overwritten

git reflog [HEAD]

P

A history of how HEAD (the "current commit") moved in time.

 

In practice, operations like commit, checkout, reset, pull, merge, rebase, cherry-pick, revert etc. are recorded.

 

Not the same as log! Although... if you only commit and literally do nothing else (even no checkout etc.) than the reflog is going to be (nearly) identical to log.

git reflog <branch>

P

A history of how the given branch changed in time.

 

Typically starts with a record of "git branch" or "git checkout -b" operation.

 

Typically some portions of branch's reflog are going to overlap with HEAD's reflog. When a branch X is checked out, then by e.g. committing you're moving both HEAD and that branch X.

Painless Linear History in Git

By plipski

Painless Linear History in Git

  • 1,493