Git-ting Personal with git reset, revert, merge, and rebase
Dealing with change is hard for everyone, but it doesn’t have to be quite such an ordeal!
In git world, you can pretend your mistakes never happened. You’ve got the help of git reset and revert.
When you finally grow and learn from your mistakes, you can be ready to work with others. Do this with the help of trusty git merge and rebase.
Now that I’m done saying that… here’s some information on the differences between these git methods, how, and when, to use them to your advantage.
git reset and revert (the “undo” commands)
git reset
git reset
unstages the specified file and discards commits in a private branch or throws away uncommitted changes.
git reset b
// where b is the commit you'd like to change reset back to
This is great for undoing changes that haven’t yet been shared with other developers. Compare this to if you wrote a new chapter to a book that hasn’t been published and just wanted to act like it never happened. The cmd/ctrl + z
of the git world.
git reset
can modify the history of a repository and should not be used on shared branches/repositories as it could cause conflicts you’d have to deal with later.
Reset flags:
--soft
: Does not alter the working directory.--mixed
: The default. It updates the staged snapshot but doesn’t alter the working directory.--hard
: Updates both the staged snapshot and the working directory to match your specified commit.
You can either specify a file path for git reset
or it will work on the full commit.
git revert
Takes a specified commit and creates a new commit that undoes the changes from that specified commit. These can be the last changes you committed, or you can specify commits further back from the HEAD
.
git reset <commit id> // in this case you would specify the id of the blue circle
git reset <commitid>
// takes you back to the specified commit (blue circle)git reset
takes you back to the commit specified (blue circle), effectively undoing later commits (red square). Whereas:
git revert <commit id> // in this case you would specify the id of the red square
git revert
adds a new commit (blue circle) which undoes the changes from the specified commit (red square). The original commit you are reverting would still remain intact in the project history.
This is much safer for public branches/repositories since it undoes the specified commit by making a new commit with those revisions and doesn’t rewrite any commit history.
Differences: git reset HEAD
is good for undoing uncommitted changes in a private setting. git revert
is a tool for undoing committed changes in a public repository.
git merge
and git rebase
These two commands both do very similar jobs — both are used to combine changes from one branch with another. When working with other programmers who make changes you also need to implement, these commands can be super necessary and helpful to understand.
git merge
Using git merge
allows you to create a new commit that merges the specified branches together into one.
git switch main // main might be substituted for master in older projects
git merge <name of feature/bugfix branch you want to merge back with main> // in the below example: "Some Feature"
Before the merge:
After the merge:
You can see that a new merge commit (the blue circle) has been added to combine these branches back together. All previous commits are still accessible and the history is not changed.
Weaknesses: You have an extra commit just for this merge. A lot of developers don’t love this approach on larger projects because it can make the project path very complex and difficult to follow.
Strengths: Non-destructive. Doesn’t change or remove any of the existing commits.
git rebase
Using git rebase moves the entire new branch to begin on the HEAD of the current main branch (Makes the main the new base for the rebased branch). This makes everything into one linear path by creating brand new commits on the main branch for each of your commits on the feature or bugfix branch.
git checkout <feature branch name>
// where "feature branch name" is the branch you want to rebase back to the main/master branchgit base <main>
// where main is the name of the branch you'd like to rewrite/rebase your feature commits to, usually the main or master branch
Weaknesses: Destructive, changes/rewrites history by changing commit names when re-written on base. Harder to tell what was done since there is no merge-specific commit. Not good to do with shared work since it changes commit references other people may be working off of. The golden rule of rebasing — don’t use on public branches!
Note: You can use other git rebase commands to make this path easier to track. I won’t go into detail about them here, but you can look into rewording commits, dropping them entirely, or squashing branches into single commits.
Strengths: Linear project path, very clean and easy to follow. No extra merge commits to muddy the path.
All images from https://www.atlassian.com/git/tutorials