1

I have already read a lot but merge and rebase still confuse me.

I have 2 branch -- Develop and Feature, the Feature branch is branched from one of Develop commits. I use Dx to represent the commit of Develop, and Fx to represent the commit of Feature, where x denotes the number.

In the beginning, I want to add a new feature so I branch a Feature from Develop

Develop D1----D2
               \     
Feature         F1

after some days, I pushed some commits in Feature, and so does Develop.

Develop D1----D2----D3----D4
               \
Feature         F1----F2----F3

I found that the Feature need the updates of Develop, so I decided to apply the D3 and D4 into my Feature

In my thought, rebase is a better choice here, and my log would be like

Develop D1----D2----D3----D4
                           \
Feature                     F1----F2----F3

But in fact, the log become

Develop D1----D2----D3----D4
               \
Feature         F1----F2----F3----D3----D4

and now is my problem... Should I use merge or rebase in this situation?

I think rebase is better here, but I have found a golden rule in some websites, such as git-scm.com told that Do not rebase commits that exist outside your repository.

In my situation, the D3 and D4 are the commits that exist outside my repository?

kowsky
  • 12,647
  • 2
  • 28
  • 41
CenaWang
  • 91
  • 7
  • That doesn't look like commits that exist outside of your repository. Is there a reason that the ordering is a problem? It would have been better to merge instead or rebase in the first place and your log would be clearer, but if those are actually the same commits (D3 and D4) on both branches you should be ok. – Ilion Mar 13 '17 at 04:29
  • sorry, it is my fault, the D3 and D4 are different commits, they have different SHA. I should use D3' and D4' in Feature. – CenaWang Mar 13 '17 at 04:33
  • `so I decided to apply the D3 and D4 into my Feature` ... what does this mean? How did those two commits end up on the HEAD of your branch? – Tim Biegeleisen Mar 13 '17 at 04:53
  • 1
    Realize that your question is almost moot at this point because you already brought `D3` and`D4` into your branch; there is nothing left to merge or rebase. – Tim Biegeleisen Mar 13 '17 at 04:55
  • Sorry, Tim. those two commits are on the HEAD of my branch because I tried to rebase Feature on D4. – CenaWang Mar 13 '17 at 05:11
  • The key to understanding this is that `git rebase` *copies* existing commits, then *abandons* the original (pre-copy) versions. As long as you are the only one who was *using* the originals, when *you* leave them behind, they're really gone. But if someone or something else—another branch or another repository—has the originals and keeps them, you now have both the originals *and* the copies. – torek Mar 13 '17 at 05:42
  • hi, torek. You mean that if the Feature branch is used by only one person, then everything is fine, right? – CenaWang Mar 13 '17 at 05:58

3 Answers3

0

To my understanding, You can only merge in this situation. Reason being you have already pushed some commit of feature (I am guessing at least F1). Which means those commit cannot be rebased otherwise you would mess the whole thing.

(Unless you wanted to rebase commit which are not pushed - but then that means breaking feature commit to two part, which may not be good depend on your situation)


Edit to clarify a bit more from comment

Like everything in computing, it depends what your intention is:

I use rebase to clear up my local commits, I try to commit as often as possible, that means it could be really messy sometime, so I would use rebase to clean it up before pushing.

So my rule of thumb is rebase is used for serious of local commits which need cleaning up. Hence if you are at stage cleaning up your commit, do so.

If putting this more to your scenario,

if feature is developed solely by you, then I would use rebase for merging (since nothing will be pushed to central repo until done) - which is not your case.

As feature may be develop with different pepole, you may have to push (like your case), in this case the only option is merge.

I am guessing your D3 and D4 are more like hotfixes (which wanted to be apply early), then sometime the way to do it is there will be branch out form develop called hotfix which develop and feature both merge in to.

Alan Tsai
  • 2,465
  • 1
  • 13
  • 16
  • Hi, Alan, that means I should do rebase on those commits that have not already pushed?(btw, I am also from taiwan. :D) – CenaWang Mar 13 '17 at 04:46
  • I have edited the answer response to your comment (wow, my first time answer a question for person same country as I am. If my English is not easy to understand, get in touch, I can explain in Chinese XD) – Alan Tsai Mar 13 '17 at 06:00
0

Actually, you can do either merge or rebase. Rebasing alters the branch history permanently but results in a cleaner log.

Example starting from develop branch


INITIAL STATE:

Develop*  D1----D2

CHECKOUT new feature branch: (git checkout -b feature)

Develop  D1----D2
                \
Feature*         F1

INTERIM:

Develop  D1----D2----D3----D4
                \
Feature*         F1----F2----F3

MERGE (git pull upstream develop):

Develop  D1----D2----D3---------D4
                                  \
Feature*         F1----F2----F3----[D3+D4]

Introduces a new merge commit.


REBASE (git rebase upstream/develop)

Develop  D1----D2----D3----D4
                            \
Feature*                     F1'----F2'----F3'

This alters the history of feature branch and changes the SHA of all commits in the feature branch. This is the reason why rebase is not recommended on branches pushed to remote.

The remotes/upstream/feature branch is now different from local/feature and you wont be able to update the remote branch with a git push upstream feature.

To reboot the branch with the current changes, use the --force, -f flag

# Use with caution. Cannot be reverted.
git push upstream feature -f

With this step, any users that may have pulled / forked your branch are now essentially detached from your branch and won't be able to push to the feature branch upstream without altering their local history too.

ashmaroli
  • 5,209
  • 2
  • 14
  • 25
0

But in fact, the log become

Develop D1----D2----D3----D4
               \
Feature         F1----F2----F3----D3----D4

I do not think this is correct. According to this, the log should look like this

Develop D1----D2----D3----D4
                           \
Feature                     F1'----F2'----F3'

In fact, your situation looks very similar to the master-topic branch example in the link I provided above.

You already achieved what you wanted in your code: You have the changes of your master as well as your Features' changes. The problem now is the synchronization with your remote.

Do not rebase commits that exist outside your repository.

You already pushed the commits in your Feature branch. This means, someone could have been pulling these commits and is currently working on top of them. When you do a rebase as above, note that your commits F1,F2,F3, become F1',F2',F3'. These are completely new commits, although they contain the same changes. If you push them to your remote now, overwriting the old history, people who work on top of the old commits will run into problems when they want to push their work.

Rebase like this always introduces new commits. Git will not allow you to push these commits, if you already pushed your old ones, unless you use the --force option. In general, it is safer to rebase only local changes, where you can be sure nobody works on top of them and it's thus safe to modify their history.

See this question for another explanation.

EDIT: As Tim Biegeleisen stated in the comments, no merge or rebase is necessary, since you already have all your changes. If you push now, however, you would have to perform a force push, since you rewrote your' Feature branches history, which is not advisable if anyone else might have worked on top of your changes.

kowsky
  • 12,647
  • 2
  • 28
  • 41