Git Snippets
A collection of git snippets gathered for my own reference.
Oops! Undo
There are various ways to undo a change or go back to a previous state.
Go back
If you made a commit you want to change, use reset
it resets the pointer for the entire repository back to that moment. You can use reset with a hash or ~ back from head. This example would move back two commits:
git reset --hard HEAD~2
The --hard
flag is optional, if you leave it off it will only unstage the changes, leaving the diff in your working repository.
Revert Commit(s)
If you have a commit you want to reverse but not change the entire repository back to that point, you can use diff
or revert
.
git diff SHA..SHA^
The ^
means the hash before, you could also get the diff between two different hashes.
Using git diff
shows you the diff of the change, if you want to apply it to your working files pipe into git apply
.
git diff SHA..SHA^ | git apply
The git revert
command will do the same as above in a single command, it will also commit the change to your local repository, use --no-commit
to skip.
git revert SHA
Complete Reset Local to Remote
Give up and try again, reset your local branch to remote.
Pull in the last changes, and then do a hard reset to that branch.
git fetch REMOTE
git reset --hard REMOTE/BRANCH
Query Search Git
Show names of changed files
Use the --name-only
flag with git-diff to show the list of files changed:
git diff --name-only
I'll use this with vim to edit a set of files, the following will open in vim all changed files:
vim $(git diff --name-only)
You can also use this for staged files:
vim $(git diff --name-only --staged)
Search By Date
Use git log
with --after
and --before
to search by date, be aware of times to cover the whole day. For example:
git log --after="2020-03-01 00:00" --before="2021-08-31 23:59"
Commit Date
Speaking of dates, you can alter time by specifying the commit date, in case you need to fill a gap or two in your commit streaks.
GIT_AUTHOR_DATE='Fri Jul 26 19:32:10 2013 -0400' GIT_COMMITTER_DATE='Fri Jul 26 19:32:10 2013 -0400' git commit
Remote Repositories
New Remote Tracking Branch
A note to myself to not look up how to create a local branch and set it to track a new remote branch in one command. It takes two.
# Create new local branch
git switch -c limb
# Push it up to remote and track
git push --set-upstream origin limb
Checkout Pull Request
If you want to checkout a pull request, likely from someone else to your repository, you can using the PR number and not have to create a new remote to their repository.
git fetch origin pull/64/head:pr64
git switch pr64
Update Fork from Upstream
- Pull in latest changes from upstream.
git fetch upstream
- Switch to trunk branch on fork.
git switch trunk
- Bring fork master up to date
git pull --rebase upstream trunk
- Push changes back up to fork remote
git push fork trunk
- (optional) Rebase a branch to a tag
git checkout my-branch
git rebase v1.9.1
Fix Merge Conflicts
A quick list on how to fix merge conflicts on your branch, more info on preserve-merges flag from here. The process is to update your local master with latest, merge that code onto your branch, update any conflicts and commit those back to your branch.
git switch master
git pull
git switch branch
git rebase master --preserve-merges
At this point you will see the conflict, git status
will show the file(s) in conflict. Resolve the conflict by editing, adding, and then committing.
You can then continue down the line using git rebase --continue
until all conflicts are resolved.
To commit your changes upstream, you will need to force push up: git push origin branch -f
Squash Everything
If you want to rebase and collapse a repository down to a single commit, sometimes this is useful when converting a private repo to a public one and you don't want to leak any intermediary files.
git rebase -i --root master
Split a directory to own repository
You can create a new repository out of a sub-directory that already exists in a repository. First, clone the repository that holds the directory.
git clone git@github.com:username/fullrepo
Switch to the repository directory and filter on the directory you want to create the new repository from. The example uses subdir
and trunk
branch, you can specify your branch name.
git filter-branch --prune-empty --subdirectory-filter subdir trunk
Look at your repository, it should now simply consist of the contents of your directory. You can now switch your remote to be a new repository. So if you created a new repository on github called subdir
.
git remote set-url origin git@github.com:username/subdir
Then simply push your changes to your new repository and you're all set.
git push -u origin trunk