[tutorial] Git Survival Kit pt.3: Integrating the changes

Hi again, and welcome to our third Git Survival Kit tutorial post! If you’ve read Covering the basics and Diggin’ deeper, you’re now ready to take on one of the coolest Git features: integrating the changes between separate branches. Besides that, we will look into another useful concept called stashing. Let’s begin then.

Stashing your work


 

Let’s say you modified something in your working directory and don’t want to make a commit yet. If you need to switch to a different branch in a situation like that, Git won’t let you. The solution is to stash your changes. Stashing takes your modified and staged changes – and saves it on a stack.

git stash

To see your stashed changes, run:

git stash list

To restore your most recent stash, you can use:

git stash apply

or:

git stash pop

To restore one of the older stashes, use:

git stash apply stash{n}

where n represents the number of the stash.

Merging changes


 

To merge changes from one branch to another, switch to a branch you want to merge into and run:

git merge <branch>

where <branch> indicates the branch you want to merge.

 

During the merge, Git creates a special snapshot with merged data and points a special commit to it. That commit is reffered to as a merge commit (C5 in the picture below).

$ git checkout master
$ git merge newBranch

In cases where Git can’t merge the files, you have to deal with merge conflicts. The conflicts arise because both branches change the same part of the file. In that case, you have to resolve the merge conflicts, stage the files and commit. The merge is then completed.

 

Instead of fetching data then merging, you can do a git pull which does the same thing. When you run:

git pull <remote>

it fetches data from the specified remote and then tries to merge it into the branch you’re currently on.

Rebasing changes


 

Besides merging, you can integrate changes between branches by rebasing. The principle is simple: you take the changes from one branch and apply them on top of another one.

 

To do that, switch to a branch you want to rebase and run:

git rebase <branch>

where <branch> indicates the branch you want to rebase onto.

 

You can also write:

git rebase <branch> <topic>

which checkouts to <topic> and then runs:

git rebase <branch>
$ git checkout newBranch
$ git rebase master

To rebase a topic branch based on one branch on top of another branch, use –onto option:

git rebase --onto <branch> <topicBranch> <topic>

Here, <topic> indicates the branch you want to rebase and <topicBranch> is the parent branch of <topic>.

To rebase, or not to rebase


 

The main difference between rebasing and merging is that rebasing changes development history. It discards existing commits and creates new ones which results in linear, cleaner history. So why would anyone continue to merge stuff if you can rebase everything? It’s simpler, allows you to revise your commits and results in a clean history. The short answer is: because rebasing can be extremely dangerous.

 

Let’s say you work together with your team on a big project. You merge your local branches, commit and push to the server. Your teammates then pull down your work and continue to work on it. You then decide it would be better if you rebased your changes so you change everything and push again. The consequence is that the part of the project that multiple people have based their work onto is now changed. Every one of them has to pull again and will have great trouble while merging.

 

The basic rule is: do NOT rebase commits that exist outside your repository. In other words, it’s perfectly fine to rebase everything while making changes only in your local repository. Once you push your work, it just isn’t worth the trouble.

 

If you do find yourself in a situation like that, instead of a normal git pull, use:

git pull --rebase

which will first rebase your work on top of your teammates’ pushed work and then merge.

No Comments

Post a Comment

Comment
Name
Email
Website