This is the second part in a series
Fixing your commit:
Sometimes, you make a mistake committing something. A file can be missing, or the indentation is not perfect, or you had a typo in your commit message. If you are using some other source control softwares such as Team Foundation Server you’re done with that. The only option you have is to check in another change set to fix your previous one (in case you have a typo in your commit message, be done with that). Git is so much more powerful in terms it allows you to rewrite history.
To fix a commit, make a change, then commit as usual, but this time, Select the “Amend commit” checkbox:
Always think twice before doing this
And now the commit has changed: note its SHA before:
SHA before amend commit
SHA after amend has changed
The commit hash has been changed completely. Author date has not changed, but the commit date is changed. This action is equivalent to
git commit --amend (no short form) in Git bash.
If the commit you wanted to fix was not pushed to any remote branch, you’re good now. But what if you already pushed it some where? Now after you amend your commit, if you try to push your branch to remote branch, this is what happens:
No, something is wrong
Now that’s what happens when you rewrite a branch history. When you push a branch, Git assumes that your branch is newer than the remote branch – in terms in contains newer commit than the remote one. We have a new commit, yes, but we also have not the old commit. Your branch is now seen as “behind” the remote branch. (Which is not entirely, you just has branched it).
The way to solve this is to go nuke and use Force option.
The dangerous option
With this option, you now can push. But hold on. What does it do?
It add a flag to tell Git: I don’t care what the remote branch looks like. Here what’s I want it looks like.
IT CAN BE VERY DANGEROUS.
I told you to think twice before amending your commit. Then you should think thrice before pushing your branch with Force Push option. Never, ever do it on a public branch. Do it on your own branch with great care.
The Force Push option in Git Extensions is equivalent with
git push -f or
git push --force in git bash.
From the beginning we’ve been only working on master branch. This is not the way you work with Git in real-world scenarios. This is how most of us work:
- Create a branch from a source branch (check out).
- Do the work on that new branch.
- Merge from new branch to the original branch, usually via a review (If you’ve ever heard about “Pull request”, this is it).
Why? In collaborating environment (which is the main pont of Git), if multiple people work on same branch, it’ll be a nightmare when there are multiple commits come in the same time. You’ll have hard time merging conflicts between commits. Further more, having one branch means higher chance to screw it up. (Things as Pull request do not eliminate such catastrophe, but at least it makes those less likely to happen).
Let’s create a new branch by checking the remote branch out. Right click on the branch you want to branch out ⇒ Checkout branch/Branch you want to select.
The checking out options
There are plenty of options here. But we will go through them one by one.
- We can check out local or remote branch. If we check out local branch, it’s actually “Switch to that branch”. What we actually care about is Check out remote branch.
- If you already checked out the remote branch, you will have an option to reset your local branch. That means, if you already did something with your branch (add some commits, for example), those changes will be reset and you will have a branch which is same as the remote branch. If you have not checked out the remote branch, you have an option to create it locally with same name.
- You also have the option to create a branch with a different name. For example, while the remote branch is
origin/master, I can create a local branch named
branching-chapter. This new branch
trackthe remote branch. That means, next time you pull,
branching-chapterwill be pulled from
origin/masterby default. (We will talk more about this in upcoming sections)
- You also have the option to checkout the remote branch. This option does not actually work. Choosing this means you will have a “non branch” with point to no remote branch. We should skip it for now.
The second option is what you want to do with your local pending changes:
Don't changemeans your local pending changes will be kept as-is. If your local pending changes have
conflicts(we will talk about this soon enough), this option will fail.
Mergemeans your local pending changes will be merged with the changes from the branch. You then can merge any
conflictsbetween your local pending changes and the remote branch.
Stashmeans your local pending changes will be kept locally in a
Resetmeans your local pending changes will be lost – your local branch is now the same with the remote branch. Unless you’re absolutely sure this is what you want to do, DON’T use this option. Once uncommitted pending changes are lost, they are lost forever and there is no way to get them back.
Stash changes in Git Extensions
The equivalent command in Git bash is
git stash. To list the existing stashes in your machine, use
git stash list. And to get back a stash, use
git stash apply
I usually don’t use
stash. The reason was if I have half-done work, I can make a commit and push it to my private branch, so I can continue to work at home (I don’t have to, but I usually want to), or if the next day I call in sick, I can ask one of my colleagues to take over my work. Stash also does not have a commit message, so I will have a hard time figuring out what I’ve done last week in the Monday morning.