简体   繁体   中英

git pull feature branch just after rebasing feature branch with master branch will revert rebase changes

I just performed a git rebase from master to my feature branch with steps below:

$ git checkout master
$ git pull
$ git checkout feature
$ git rebase master

Then post rebase I tried push as below:

$ git push origin feature

Above command throwed error saying something HEAD's of my local and remote are not same or something and recommended I should git pull instead. So then I did pull being on feature branch as below:

$ git pull

Now with some googling I got to know that I should have done --force push.

Hence my doubt is the changes which I got as part of rebase are gone in my local branch since I did git pull or they are there and I can still do a git push from local to remote as below:

$ git push origin feature --force // maybe force not req. now

Or do I need to do a git rebase master again?

One more thing I wanted to ask is that suppose my new feature will never modify exiting files in master branch and will contain only new files then does it make sense to do rebase, because when all the files are newly created in feature branch and then even if master branch has moved few commits ahead still merging from feature to master should be doable without conflicts? Am I right or missing something here.

Also while I was doing rebase there were lot of conflicts that I had to resolve, but those conflicts never came when I merged those commits the first time, why on replaying same commits conflicts are coming? I am the only one working on the feature branch.

Also what is the reason for duplicating commits, what I mean is for example if I have a feature branch with below git log:

commit_hash2 My Second Commit
commit_hash1 My First Commit
commit_hashX Latest commit of master branch when we created feature out of it

Now suppose master got one new commit say with commit_hashY, then post rebasing feature with master (git rebase master) I feel git log in feature should look like below:

commit_hash2 My Second Commit
commit_hash1 My First Commit
commit_hashY Current Latest commit of master branch
commit_hashX Latest commit of master branch when we created feature out of it

But I usually see now duplicated commits something as below:

commit_hash4 My Second Commit
commit_hash3 My First Commit
commit_hash2 My Second Commit
commit_hash1 My First Commit
commit_hashY Current Latest commit of master branch
commit_hashX Latest commit of master branch when we created feature out of it

Why this duplication, what am I missing, in which scenario someone would be preferring these extra duplicate commits, just trying to understand thought behind this git design.

Looks like I asked too much:P

It's unfortunate that Git suggests that you pull before pushing after a rebase. You pretty much never want to pull in that case and so many people get tripped up by this and end up in your exact situation. (The reason Git tells you to pull is simply because your local commit IDs have changed, and Git detects that there are commit IDs on the remote branch that aren't in your local branch, and Git doesn't know they are older versions of your local commits that you no longer need. And BTW, to address your updated question, this is also why you have duplicated commits: you rewrote your commits with rebase and then pulled in your older version of it from the remote, rather than force pushing and replacing them.) You simply have to remember that after a rebase you will oftentimes be prompted to pull, and you need to force push instead. Fortunately though, this is very easy to recover from. Basically, you want to get back to where you were before you did the extra pull, which would be the commit ID that you were on after you finished the original set of commands:

git checkout master
git pull
git checkout feature
git rebase master

To find the commit ID you were on after that rebase, you can use the command git reflog which will show you all the commits you've been on recently, sorted by most recent first. If the commit IDs along with the command and branch names isn't by itself enough information to be sure which is the correct one, then you can open another command line and run git log [commit-ID] against different IDs to see which one is right. You'll want to use the one that has your commits on top of the latest master . If all you've done since the rebase was a pull, it's likely to be the second commit ID from the top. Once you've identified which commit you want to go back to, you can set your branch back to it with:

git reset --hard [commit-ID]

Now you'll be back to after the rebase as if you didn't do the pull, and now you can push it out properly:

git push --force-with-lease

Note, when pushing, it's almost always better to use --force-with-lease instead of --force .

Regarding your question about if it makes sense to rebase if you are only ever adding new files, there is no yes or no answer. This is because you never need to rebase, ever, if you are dead set against it. But note there are 2 different purposes of rebases: rebasing onto a branch (to get the latest changes and simplify the commit graph), and interactive rebasing ( rebase -i ) to fix up your commits. I would hope that those that are against rebasing onto a branch would at least still interactive rebase, though I know some people are even against that too for some reason. Personally, I love rebasing and I probably do it 20 times per day (both branch and interactive). I would still do it in your situation too, and also again immediately before completing a PR so that the commit graph is easier to follow and has fewer unnecessary merge commits in it. But coming from a Git Flow background, I still force a merge commit at PR Completion so that I can see all the commits that were part of the PR, even though a fast-forward merge would be possible since I just rebased before completion.

Side note : I usually recommend deleting your local copy of the master branch and never checking it out, The reason is that it gets stale quickly and to keep it up to date you have to continually check it out and pull, and right after you do that it could be out of date again soon, and you can always save a step without using it, by simply using origin/master instead. For example, you could have done this:

git fetch # update all remote branches
git checkout feature # probably you were already on feature and can just skip this!
git rebase origin/master

That's much more efficient and you never have to worry about keeping your local copy of master up to date.

Before you pulled from remote feature branch, I think the steps are correct.

Maybe a good practice is that you should keep local master branch as new as the remote one. Then rebase you feature branch. After all conflicts are resolved. Force push the feature branch to update remote one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM