I'm still in the process of getting confident with Git so am still treading carefully with some elements of it.
The list of commands I have for rebasing my private branch as I work (so it does not become out of date by the time I'm finished) is:
# Prepare the new private branch
git checkout develop
git pull origin develop
git checkout -b new-feature
# work, commit, work commit, time to rebase...
git checkout develop
git pull develop origin
git checkout new-feature
git rebase develop
# continue working...
What I'm wondering is if I can save a few steps and do the following when I want to rebase:
# on the new-feature branch
git fetch
git rebase origin/develop
# continue working....
Or will that cause problems when I come to merge my private branch with develop? If it's ok, do I need to merge origin/develop with develop if I've already done that in my private branch?
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.
来源:https://stackoverflow.com/questions/18524512/least-number-of-commands-to-rebase-private-branch