2

Someone marked this as duplicates, but it does not tell why git rebase as no conflicts while git pull has

I have two clones of the same repo, C1 and C2 and their HEADs are both at commit M1 which has some changes to file F.

Assume no .gitconfig file and .git/config for the file is the default generated by git

In C1

  1. I modify F (at the same place that M1 modified F)
  2. git commit -a --amend --no-edit to rewrite M1, which results in a new commit M2.
  3. git push -f to overwrite the remote.

In C2

  • I do git fetch. So the origin/master == M2 while HEAD == M1

since M1 and M2 both modified F, any of the following commands will enter merge conflict state:

  • git merge origin/master
  • git merge
  • git rebase origin/master
  • git pull

However, the following commands does not trigger merge conflicts and set HEAD to M2

  • git rebase
  • git pull --rebase

Questions

  • Is this behavior correct by design?
  • What is the difference between git rebase and git rebase origin/master
  • What does git pull --rebase do?

Previously, I always thought

  • git pull is the same as git fetch && git merge origin/master
  • git pull --rebase is the same as git fetch && git rebase origin/master

But this experiment invalidates my thought.


The situation does not change even if I commit another M3 on top of M2 and push in C1. In C2 it will still reset to M3 and the M1 is lost.

doraemon
  • 2,296
  • 1
  • 17
  • 36
  • Possible duplicate of [Difference between git pull and git pull --rebase](https://stackoverflow.com/questions/18930527/difference-between-git-pull-and-git-pull-rebase) – plalx Jan 17 '19 at 03:10
  • No, please do not mark it as duplicate. – doraemon Jan 17 '19 at 03:11
  • That one says: `git pull --rebase = git fetch + git rebase` and it does not tell why `git rebase` does not result in merge conflicts as `git rebase origin/master` does – doraemon Jan 17 '19 at 03:13
  • Read the second answer. – plalx Jan 17 '19 at 03:18
  • How can it explain the things happening here? I have `o - M1` and `o-M2` and M1 and M2 are different. If you know the answer, could you please write a formal answer to elaborate why putting `M2` onto `M1` should not result in conflicts? – doraemon Jan 17 '19 at 03:21
  • OP, you need to visually see what's going on in a rebase and that will clear up 99% of your questions. Try playing with this here and that should help immensely: https://onlywei.github.io/explain-git-with-d3/#rebase – BenKoshy Jan 17 '19 at 03:42
  • @BKSpurgeon, I cannot do clone there. Neither does modify files and `commit --amend` – doraemon Jan 17 '19 at 03:49
  • To me, this behavior makes perfect sense. You haven't made any changes in C2, so there are no commits in C2 that require rewriting, and it should just fast-forward. M1 isn't a new change in C2, because C1 also had M1 before you started to make changes in C1. – mbj Jan 17 '19 at 03:53

1 Answers1

0

git merge attempts to look at the differences between points M1 and C1 and the differences between points M1 and C2, and merge them together.

git rebase puts you at point M2, then applies each of the changes from point M1 to point C2 that was not also on the path to point M2 in sequence. Taking this approach, it's able to get a much better understanding of what is pertinent and what isn't, so many things that seem like conflicts in the merge approach are much more obvious to work out.


While a lot of developers seem to like to do as few commits as possible, git rebase actually works best when each of the commits involved was small. It all seemed like magic to me, until I tried to basically do the same thing by hand on a CVS repository. Coworker A's change, which was just a single commit, was no easier to apply with the rebase concept, because it was all one thing. But switching to his update, and applying Coworker B's dozens of tiny commits to it worked very well to show exactly what was intended for each update.

Ed Grimm
  • 548
  • 5
  • 13
  • Thanks for your reply, could you please change your `ABC` to the letters used in the OP? According to `git help rebase`, in `C2`, it will save the commit `M1` to somewhere, and reset head to `M2`; then apply the changes saved (`M1`). Obviously, this will result in conflicts. – doraemon Jan 17 '19 at 03:37
  • tried using `git checkout origin/master && git cherry-pick M1`. – doraemon Jan 17 '19 at 03:38
  • I will make an attempt, but I'm uncertain I will get it right, because you seem to have a few terms wrong, and I can see a number of different ways you could be thinking them. – Ed Grimm Jan 18 '19 at 05:47