Git
Rebasing
To Ancestor
You created a sequence of commits, feat-1
and feat-2
, and you realize
"hrmm, feat-2
doesn't actually depend on feat-1
. I could make both of
these PRs against main
at the same time."
Given a repo like this:
git init touch A && git add A && git commit -m "A" touch B && git add B && git commit -m "B" git checkout -b "feat-1" touch C && git add C && git commit -m "C" git checkout -b "feat-2" touch D && git add D && git commit -m "D"
gitdot --png
You want feat-2
and feat-1
to both be based off main
. You can't just
rebase feat-2
on main
:
git checkout feat-2 git rebase main
gitdot --png
Nothing happens, because a rebase replays commits onto the new base, and in
this case that would just replay the feat-1
and feat-2
commits on main
again (changing nothing).
Solution: only reply the feat-2
commit on man
using --onto
with a
cut-point! The form of the command is git rebase --onto <Target> <Cut
Point>
.
git checkout feat-2 git rebase --onto main feat-1
gitdot --png
To Specific Commit
Given a repo like this:
git init touch A && git add A && git commit -m "A" git checkout -b "feat-1" touch B && git add B && git commit -m "B" git checkout main touch C && git add C && git commit -m "C" touch D && git add D && git commit -m "D"
gitdot --png --msg
Rebasing feat-1
on main
would make B
point to D
. But say we wanted to
rebase B
on to C
instead?
git checkout feat-1 git rebase --onto C
I Accidentally…
Commited to the Wrong Branch
You locally committed to main
instead of develop
, but you haven't pushed
the commit yet.
- Soft-reset main back to origin/develop
- The committed changes will now be staged
- Switch to develop branch
- Commit staged changes
git reset --soft origin/develop
Rebased Remote Branch
You rebased, and then remembered that the branch you were on has already been pushed to a remote repo. You shouldn't push this rebase!
- You need to return the current branch to where it was before the rebase.
Ammended Remote Commit
You ran a git commit --ammend
, then realized you've already pushed the
commit you were ammending! You can't push the ammended commit! (You can,
but that would be rewriting history on the remote server).
- Reset soft to
origin/<branch-name>
. Then the changes you just committed will be staged. - Commit again as a new commit.
Committed Locally Before Pulling Remote
Somebody pushed changes to your branch while you were still committing locally. Now your branch and the remote branch have diverged.
- Option 1: Merge remote into local. Just do a git merge of remote/branch-name.
Fixup
You make a change that ought to have been part of a previous commit, but that
previous commit is not the last commit (so you can't just --amend
the last
commit).
First, make this new commit and mark it as a fixup
of the offending commit:
git commit --fixup fb2f677
Next, run a rebase --squash
, which does a rebase where fixup commits are
squashed into the commits that they fix up. The commit hash is the commit where
the rebase is started from.
git rebase -i --squash ac5db87
Refs
HEAD
HEAD is usually a symbolic ref, meaning it points to another ref. The exception is when you are in a detached HEAD state, in which case HEAD points directly to a commit.
git symbolic-ref HEAD
Some ways to print the SHA of the HEAD ref:
git rev-parse HEAD
git log -1 --format='%H'
Branches
Current branch name:
git rev-parse --abbrev-ref HEAD
Diff
Diff a branch with the commit you branched from.
git diff my-branch...main
First Commit
Some ways to find the first commit in a Git repository:
git show $(git rev-list --max-parents=0 HEAD)
git log --reverse
Latest commit
Fun way to get the latest commit hash on a repo! (Or really, any commit hash for any ref). You don't even need the repo cloned locally.
git ls-remote \ https://github.com/cfclrk/rules_clojure.git \ refs/heads/master
Files changed in commit
git diff-tree -r --no-commit-id \ --name-only $sha
Tags
Get Project Version From Tag
I got this from cider here.
git describe --tags --abbrev=0
Is HEAD a tag?
If HEAD is a tag, this will print the tag name. If not, it prints nothing.
git tag --points-at HEAD
List Tags Matching Pattern
git tag --list "v*"
Project Root Dir
git rev-parse --show-toplevel
Tools and Resources
- git-quick-stats: Bash script that shows cool stats of git repos.