Least number of commands to rebase private branch

随声附和 提交于 2019-12-06 14:28:29

The fetch-and-rebase as outlined is just fine. For the second question, I'm not quite sure what you're asking, so the below covers all bases, as it were.

(Note that git pull is mainly just git fetch followed by git merge, unless you configure it to do rebase for instance. I'm going to use only git merge below, on the assumption that you've done a sufficiently-recent fetch.)

Here's what you'll get, assuming ongoing activity on origin/develop and a starting point at commit D1 on origin/develop:

... - M6                          <- master, origin/master
        \
         D0 - D1                  <- develop, origin/develop
                \
                 N0 - N1          <- HEAD=new_feature

Now you do git fetch and "they" have added D2 and D3. I'll leave out master and origin/master, assuming they haven't moved (if they have it doesn't matter anyway), leaving more room for local stuff:

        D2 - D3                   <- origin/develop
       /
D0 - D1                           <- develop
       \
        N0 - N1                   <- HEAD=new_feature

So now (with HEAD=new_feature, all pointing at commit N1) you do:

git rebase origin/develop

and git does this, making two new commits N0' and N1':

                N0' - N1'         <- HEAD=new_feature
               /
        D2 - D3                   <- origin/develop
       /
D0 - D1                           <- develop
       \
        N0 - N1                   [abandoned]

The abandoned commits eventually fall away (I'll leave them out below) and meanwhile you add N2, and they add D4. So, you git fetch and git rebase origin/develop, giving:

                N0' - N1' - N2    [abandoned]
               /
              |     N0''-N1''-N2' <- HEAD=new_feature
              |     /
        D2 - D3 - D4              <- origin/develop
       /
D0 - D1                           <- develop

As before, the "abandoned" stuff can be forgotten-about, which gives you a nice clean history of your changes (however many times rebased) extending out from the end of origin/develop.

At any point along the way you can, but do not have to:

git checkout develop && git merge origin/develop && git checkout new_feature

Since you haven't added any commits onto D1, this just fast-forwards, so that develop points to the same commit as origin/develop.

Let's say you haven't manipulated the local develop yet, but it's time to merge in new_feature, and you now have this:

                    N0''-N1''-N2' <- HEAD=new_feature
                    /
        D2 - D3 - D4              <- origin/develop
       /
D0 - D1                           <- develop

Presumably you'll want to merge up through commit N2' in the above diagram with the endpoint of origin/develop. You can certainly do this now:

git checkout develop           # get HEAD onto develop breanch
git merge origin/develop       # fast-forward local develop branch

which gives you this (I'll straighten out the kink between D1 and D2):

                    N0''-N1''-N2'     <- new_feature
                    /
...D1 - D2 - D3 - D4                  <- HEAD=develop, origin/develop

but the more interesting question is, do you want the final result to be:

                    N0''-N1''-N2'     <- new_feature, HEAD=develop, origin/develop
                    /
...D1 - D2 - D3 - D4

or should it look like this:

                    N0''-N1''-N2'     <- new_feature
                    /            \
...D1 - D2 - D3 - D4 ------------ M   <- HEAD=develop, origin/develop

? If you want that merge commit M, your final git merge command will need a --no-ff argument, and you need to get the local develop pointing to commit D4 first. In that case, you must do the fast-forward merge to get the develop label to point to D4:

git checkout develop           # set HEAD=develop
git merge origin/develop       # fast-forward develop to origin/develop
git merge --no-ff new_feature  # create merge commit M on local develop
git push origin develop        # and push local develop to origin/develop

If you don't want the merge commit, though, it doesn't matter where develop is pointing when you do the final merge, as it is just going to fast-forward. So, instead, you would do this:

git checkout develop           # set HEAD=develop
# git merge origin/develop     # optional: not needed, but harmless
git merge new_feature          # fast-forward local develop to new_feature
git push origin develop        # and push local develop to origin/develop

It's always a case of figuring out "what commit graph do I want to end up with" first. If you can draw the graph you want, it's a lot easier to figure out how to get there from wherever you are now.

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!