1. Remove editing local file
Sometimes the best way to get the hang of the problem is to dive into the code. Unfortunately, the changes made in the process are not very optimized, in which case reverting the file back to its original state is probably the quickest way:
git checkout – Gemfile # reset specified path
git checkout – lib bin # also works with multiple arguments
The 2 dash (-) denotes the command line feature to indicate the end of the command options.
2. Undo local commits
Sometimes it takes a long time to realize that we are going in the wrong direction, and by then many changes have been applied. That’s when git reset comes in handy:
git reset HEAD ~ 2 # undo last two commits, keep changes
git reset –hard HEAD ~ 2 # undo last two commits, discard changes
Be careful with the –hard option! It will reset the system you were working on, and all changes will be lost.
3. Remove a file from Git without having to remove it from the file system
If you are not careful when using git add, you will add a bunch of unwanted files without knowing it. However, git rm will remove it from both your staging area, as well as your file system – something no one wants. In this case, make sure you only remove the staged version, and add the file to .gitignore to avoid a second error:
git reset filename # or git remove –cached filename
echo filename >> .gitignore # add it to .gitignore to avoid re-adding it
4. Edit commit message
At this point there should be the typo, but fortunately you can fix it quite easily on the commit messages:
git commit –amend # start $ EDITOR to edit the message
git commit –amend -m “New message” # set the new message directly
But that is still not all the use of git-amend. If you forgot to add a file, just add and edit the previous commit!
git add forgotten_file
git commit –amend
Remember –amend actually creates a new commit instead of the previous one, so don’t use it to change the commit that was pushed into the middle of the repository. The one exception is that you have to be sure that no developer has checked the previous builds and worked on it, so a forced push (git push –force) will be fine. The –force option is required here because the system history has been adjusted locally, meaning push will be rejected by the remote server because the fast-forward merge is not possible.
5. Clean up the local commit before pushing
Although –amend is very useful, it doesn’t really work if the commit you want to reword isn’t the last. In this case, you will need an interactive rebase:
git rebase –interactive
if you didn’t specify any tracking information for this branch
you will have to add upstream and remote branch information: git rebase –interactive origin branch
6. Revert pushed commits
Although some of the solutions are outlined in the previous tips, some wrong commits will sometimes dominate the repository. That’s okay, since git gave you a simple way to revert one or more commits:
git revert c761f5c # reverts the commit with the specified id
git revert HEAD ^ # reverts the second to last commit
git revert develop ~ 4..develop ~ 2 # reverts a whole range of commits
If you do not want to create more revert commits but only want to apply the necessary changes to the system, you can use the –no-commit / -n option.
undo the last commit, but don’t create a revert commit
git revert -n HEAD
The manual page at man 1 git-revert also lists many other options and gives some more examples.
7. Avoid duplicate merge conflicts
One thing every developer understands, is that fixing merge conflicts sounds horrible, but dealing with a conflict over and over again (for example, in feature branches that run long) is truly a nightmare. . If you have encountered this situation, you will be happy to hear about the feature reuse recorded resolution feature. Let’s add it to the global config for all projects:
git config –global rerere.enabled true
Alternatively, you can use it on individual projects by creating the .git / rr-cache directory manually.
This is not a feature for everyone, but for those who need it it will save you a lot of time. Imagine your team is working on many different feature branches at the same time. Now you want to merge all of them together into one testable branch before release. From there you will have to deal with some conflict about merge. Unfortunately one of the branches is still incomplete, so you have to cancel the merge again. Days (or weeks) after the last branch is ready, you will merge again, but thanks to the recorded resolutions, you won’t have to resolve the merge conflict again.
The main page (man git-rerere) has more info about cases and commands (git rerere status, git rerere diff, etc.).
8. Find the commit that caused the error after merge
Finding the commit that pulled the bug after merging is quite time consuming. Fortunately, git provides a good binary search in the form of git-bisect. First you need to manifest the first setup:
git bisect start # starts the bisecting session
git bisect bad # marks the current revision as bad
git bisect good revision # marks the last known good revision
After this git will automatically checkout a revision halfway between the known “good” and “bad” versions. You can now run your specs again and mark the commit as “good” or “bad” accordingly.
After git automatically checks out the “good” and the “bad” versions. You can also re-run the spec and mark the corresponding commit as “good” or “bad”.
git bisect good # or git bisec bad
This process will continue until you find the commit that carries the bug.
9. Avoid common git hook errors
Some errors are repeated very often, but will be easily avoided if they are checked regularly or cleanup tasks are at a certain stage in the git workflow. The hook is designed for this. To create a new hook, add a file to .git / hooks. The name of the script should be compatible with one of the available hooks, a complete list of those available on the manual page (man githooks). You can also define global hooks to use in your projects by creating a template directory for git to use when starting a new repository.
10. If all fail
Here, we have covered quite a few ways to fix common errors when working with git. Most of the solutions are quite good, but there are times when it is not easy to use and have to rewrite the history of the entire branch. A good practice in this case is to remove sensitive data (for example, authorization to login for production systems) attached to the public repository:
git filter-branch –force –index-filter
‘git rm –cached –ignore-unmatch secrets.txt’
–prune-empty –tag-name-filter cat – –all
This will remove the file secrets.txt from all branches and tags. It also removes any empty commits after performing remove. Remember that this will also rewrite the history of the entire project that may broke on the workflow. And while the file is being removed, the authorization is still quite dangerous!
GitHub has a tutorial on how to remove sensitive data, and man git-filter-branch has all the details about the filters and options available.