-
Notifications
You must be signed in to change notification settings - Fork 29
git rebase rather than merge
Up until the date of this document (Dec 2012), the plainblack/Lacuna-Server-Open (pb-ls-open) repository has been managed by responding to pull requests and merging in changes from various developers.
If you look at the network graph for this period you will see that it is a complicated network of changes and merges. It is very difficult to follow back the history to see where or why a change was made.
Here is a typical example.
A---B---D pb-ls-open/develop
\
C my-ls-open/develop
This shows the Network Graph for the develop branch. (pb-ls-open represents the plainblack/Lacuna-Server-Open repository and my-ls-open represents (say) my own icydee/Lacuna-Server-Open repository.
What happened is that I did a pull from pb-ls-open when B was at the HEAD and applied my changes, C to my own git repository. In the mean-time pb-ls-open was updated (by someone else) with commit D.
If I now submit a pull request from my repository, and if that request is managed by clicking the pull button in github, it creates a merge as follows.
A---B---D----E pb-ls-open/develop
\ /
C---/ my-ls-open/develop
However it is messy even for the most simple approach. Take the following example where there was no change to pb-ls-open after I did my pull and change.
A---B pb-ls-open/develop
\
C my-ls-open/develop
When my change C is sent to pb-ls-open as a pull request. If the github button is used to automatically merge the pull request we get the following.
A---B---D pb-ls-open/develop
\ /
C my-ls-open/develop
This is because the github merge pull request always does a merge, never a fast-forward even when it could do so.
Rather than use github, carry out the merges in a dedicated local clone and do the pull requests manually.
Get into the habit of using --ff-only when doing a pull request.
When you are pulling from your own github repository to your local repository, then all merge pulls should be fast-forward (since no-one else will be pushing to your 'private' github repository).
$ git pull --ff-only my-ls-open develop
When you are merging locally (for example when merging from master to develop)
$ git checkout develop
$ git merge --ff-only master
Most of the time you should be able to do a fast-forward.
This is a little contentious. The reason is, you should never do a rebase to a public repository which someone else may have forked or cloned. This is because a rebase will rewrite the history of the commits, which if they subsequently do a pull, they will get in a mess.
However, if you are only doing a rebase on a local repository then it is fine. A little more risky is if you rebase your 'public' fork of pb-ls-open since there is a chance that someone forked from your fork! However I will assume for the purpose of this that you are the only person using your github repository. If everyone forks directly from pb-ls-open then this problem is mitigated.
Take the example as follows.
A---B pb-ls-open/develop
\
C xx-ls-open/develop
A pull request is made to merge xx-ls-open/develop into pb-ls-open/develop.
Create a repository on your laptop with read-write access to the remote pb-ls-open/develop and read access to xx-ls-open/develop. This will be dedicated to only managing pull requests.
$ git checkout develop
$ git pull --ff-only pb-ls-open develop (note 1)
$ git pull --ff-only xx-ls-open develop (note 2)
$ git push pb-ls-open develop
(note 1) a fast-forward from the pb-ls-open repository should always be possible since you should not be using this repository for development.
(note 2) this will always work, provided that all the changes on xx-ls-open are based on the current HEAD of pb-ls-open
This should result in the following...
A---B---C pb-ls-open/develop (and) xx-ls-open/develop
History has been added linearly and the changes are attributed to the person who carried out the change.
In the following example.
A---B---D pb-ls-open/develop
\
C xx-ls-open/develop
xx-ls-open carried out change C but before they could issue the pull request pb-ls-open was updated with D
This should be obvious by looking at the Network graph, either by the developer or the admin.
However, if the admin carries out the normal procedure as follows.
$ git checkout develop
$ git pull --ff-only pb-ls-open develop
$ git pull --ff-only xx-ls-open develop (note 3)
(note 3) this pull request will fail with an error something like this:-
fatal: Not possible to fast forward, aborting.
The best thing to do in this circumstance is to request that the developer does a rebase of their changes C on top of D and resubmit the request. They will then redo the pull request as follows.
A---B---D pb-ls-open/develop
\
C' xx-ls-open/develop
note. C' and C will have different commit codes, since C' has been rebased on top of D.
When this pull request is merged we will have
A---B---D---C' pb-ls-open/develop (and) xx-ls-open/develop
Refer to the following how to rebase your code for detailed instructions.