While git is surely one of my favorite tools, and increases my productivity in a sometimes unbelivable way (like when working on 3 or 5 features at the same time), some times there are operations that can be a bit tricky.

There are plenty of git tutorials and guides to get started and that explain the basic concepts. This post is not one of them. If that is what you need, you can check these great resources:

There is another quite popular resource, that doesn't focus on explaining the concepts, but on what to do if you get into certain cases (aka problems):

More on the style of the latter, in this post I'll explain some operations that are somehow advanced, I don't think are well known, but I use them frequently. So, hopefully they can be useful to others.

I've got some cool changes, but my history is a mess There are many reasons why this can happen. The one that I encounter most frequently is people opening a pull request, that does not only contain the user changes (and possibly some merges from master), but instead it contains commits from other users in the branch, as if they were part of the pull request. I never spent the time to research what is the cause, but this is what I usually recommend or do. Whether it is the previous case, or because of any other reason, if you have some changes in your branch mixed with a messy git history, the easiest way I know to go back to a state under control is: git fetch upstream : Just updating our local repository.

: Just updating our local repository. git merge upstream/master : Getting anything in the latest repository version into our branch.

: Getting anything in the latest repository version into our branch. git reset --soft upstream/master : This will make that the git history in our branch is exactly as the one in master, replacing our messy history. And it will leave in our staging area all the changes that we made, compared to master.

: This will make that the git history in our branch is exactly as the one in master, replacing our messy history. And it will leave in our staging area all the changes that we made, compared to master. git commit -m "All my changes in a single commit" Now the history in our branch will be equivalent as if we just created the branch from the latest version, and added a single commit with all our changes. As usual, we shouldn't rewrite the history if someone else pulled our commits. But if this is a local branch, or it is remote but only used to open a pull request, that should be all right.

I have changes in the working directory, and I want to change branch There are also different cases for this. The simplest case (but not common in my case) is that you are working in a branch, and want to go to make some changes to a different one, but your current changes are not in a state that you want to commit. The other cases (the ones that happen to me in practice) are: You start working in some changes, and you realize that you are in the wrong branch.

You are making some last minute addition to a pull request, and before you commit and push, the pull request is merged. So, you want to continue the work in a new branch. The problem is that when you have uncommitted changes in your working directory, and you try to change branch, you get the next error message: error: Your local changes to the following files would be overwritten by checkout preventing any branch change until you commit those changes. But committing in the current branch is not what we want. The solution in this case is git stash . With it, the changes in the working directory are saved into a stack, and the working directory becomes clean. This allows us to freely switch branches, and perform other operations. Once we have the environment ready, and we are in the branch in which the stacked changes belong to, then we can simply git stash apply . We will get the uncommitted changes back to the working directory.