Back

Explore Courses Blog Tutorials Interview Questions
0 votes
2 views
in DevOps and Agile by (19.4k points)

I've been using Git now for a couple of months on a project with one other developer. I have several years of experience with SVN, so I guess I bring a lot of baggage to the relationship.

I have heard that Git is excellent for branching and merging, and so far, I just don't see it. Sure, branching is dead simple, but when I try to merge, everything goes all to hell. Now, I'm used to that from SVN, but it seems to me that I just traded one sub-par versioning system for another.

My partner tells me that my problems stem from my desire to merge willy-nilly, and that I should be using rebase instead of merge in many situations. For example, here's the workflow that he's laid down:

clone the remote repository

git checkout -b my_new_feature

..work and commit some stuff

git rebase master

..work and commit some stuff

git rebase master

..finish the feature

git checkout master

git merge my_new_feature

Essentially, create a feature branch, ALWAYS rebase from master to the branch, and merge from the branch back to master. Important to note is that the branch always stays local.

Here is the workflow that I started with

clone remote repository

create my_new_feature branch on remote repository

git checkout -b --track my_new_feature origin/my_new_feature

..work, commit, push to origin/my_new_feature

git merge master (to get some changes that my partner added)

..work, commit, push to origin/my_new_feature

git merge master

..finish my_new_feature, push to origin/my_new_feature

git checkout master

git merge my_new_feature

delete remote branch

delete local branch

There are two essential differences (I think): I use merge always instead of rebasing, and I push my feature branch (and my feature branch commits) to the remote repository.

My reasoning for the remote branch is that I want my work backed up as I'm working. Our repository is automatically backed up and can be restored if something goes wrong. My laptop is not, or not as thoroughly. Therefore, I hate to have code on my laptop that's not mirrored somewhere else.

My reasoning for the merge instead of rebasing is that merge seems to be standard and rebase seems to be an advanced feature. My gut feeling is that what I'm trying to do is not an advanced setup, so rebase should be unnecessary. I've even perused the new Pragmatic Programming book on Git, and they cover merge extensively and barely mention rebase.

Anyway, I was following my workflow on a recent branch, and when I tried to merge it back to master, it all went to hell. There were tons of conflicts with things that should have not mattered. The conflicts just made no sense to me. It took me a day to sort everything out, and eventually culminated in a forced push to the remote master since my local master has all conflicts resolved, but the remote one still wasn't happy.

What is the "correct" workflow for something like this? Git is supposed to make branching and merging super-easy, and I'm just not seeing it.

Update 2011-04-15

This seems to be a very popular question, so I thought I'd update with my two years experience since I first asked.

It turns out that the original workflow is correct, at least in our case. In other words, this is what we do and it works:

clone the remote repository

git checkout -b my_new_feature

..work and commit some stuff

git rebase master

..work and commit some stuff

git rebase master

..finish the feature, commit

git rebase master

git checkout master

git merge my_new_feature

In fact, our workflow is a little different, as we tend to do squash merges instead of raw merges. (Note: This is controversial, see below.) This allows us to turn our entire feature branch into a single commit on master. Then we delete our feature branch. This allows us to logically structure our commits on the master, even if they're a little messy on our branches. So, this is what we do:

clone the remote repository

git checkout -b my_new_feature

..work and commit some stuff

git rebase master

..work and commit some stuff

git rebase master

..finish the feature, commit

git rebase master

git checkout master

git merge --squash my_new_feature

git commit -m "added my_new_feature"

git branch -D my_new_feature

Squash Merge Controversy - As several commenters have pointed out, the squash merge will throw away all history on your feature branch. As the name implies, it squashes all the commits down into a single one. For small features, this makes sense as it condenses it down into a single package. For larger features, it's probably not a great idea, especially if your individual commits are already atomic. It really comes down to personal preference.

Github and Bitbucket (others?) Pull Requests - In case you're wondering how merge/rebase relates to Pull Requests, I recommend following all the above steps up until you're ready to merge back to master. Instead of manually merging with git, you just accept the PR. Note that this will not do a squash merge (at least not by default), but non-squash, non-fast-forward is the accepted merge convention in the Pull Request community (as far as I know). Specifically, it works like this:

clone the remote repository

git checkout -b my_new_feature

..work and commit some stuff

git rebase master

..work and commit some stuff

git rebase master

..finish the feature, commit

git rebase master

git push # May need to force push

...submit PR, wait for a review, make any changes requested for the PR

git rebase master

git push # Will probably need to force push (-f), due to previous rebases from master

...accept the PR, most likely also deleting the feature branch in the process

git checkout master

git branch -d my_new_feature

git remote prune origin

I've come to love Git and never want to go back to SVN. If you're struggling, just stick with it and eventually, you'll see the light at the end of the tunnel.

1 Answer

0 votes
by (27.5k points)

Let us break things down here,

What do conflicts mean? Well it is nothing but parallel evolution of a same content. That means if it occurs during a merge, that means you have massive evolution on the same set of files.

In these kind of scenarios, you have two options, merge and rebase. Well, the reason why rebase is better than merge is that:

The correct way of proceeding in your case would be to perform rebase and then merge.

Rewrite the local commit history with the one of the master and then reapply the work, resolving all conflicts

Then finally merge. It will be a "fast forward" one, because it will have all the commit history of the master, plus only your changes to reapply. Note: Although, if you push your local branch for backup, that branch should not be pulled by anyone else, since the commit histories will get rewritten by the successive rebase.

In other words: The method of rebasing reminds us to fetch first. When you use this method, your work always goes on top of the public branch like a patch that is up-to-date with current HEAD.

Browse Categories

...