fredley
fredley

Reputation: 33941

I've merged a branch, but not all changes have merged?

I've merged a branch into master:

git checkout master
git merge work_branch

There were some conflicts which I resolved and committed, however there are some changes which didn't come across and I can't figure out why.

If I do git checkout work_branch I can see that the file views.py is different from master, but if I do git merge work_branch from master I get Already up-to-date. What's going on here? I want master to be identical to work_branch.

Upvotes: 0

Views: 105

Answers (4)

asm
asm

Reputation: 8898

Since you noted that you had previously git reverted I think you're running afoul of the interaction between merge and revert. git revert works by creating a new commit which exactly undoes the reverted commit. So for instance say you have the following tree.

A  -- master
|  B  -- work_branch
|  |
| /
M  -- Merge work_branch to master.
|
C -- New commit on master.
|
M'  -- git revert M (undoes B)

In this scenario you merge work_branch into master, then commit something new to master on top of the merge and then decide you that work_branch is not ready for master yet. You now have a couple options to fix this.

  • git reset --hard back to commit A and then git cherry-pick C back into master.
  • git rebase -i back to A and delete commit M
  • git revert M which creates commit M'

The first two options are basically equivalent they just have different work flows. The last option leaves you with both M and a new commit M' in your history where M' contains changes that exactly undo everything brought in during the merge that created M.

The problem arises when you decide work_branch is now ready and you want to merge it. When you do the merge you will not get any changes from work_branch which occurred in M and were undone by M'. In order to get the changes back you have to remove the effect of commit M' on your history. You have again a couple options, they are essentially the same but now you're trying to remove M'.

The simplest thing to do will most likely be to revert the revert commit. So git revert M' prior to merging work_branch again. This will also work after remerging work_branch but it may cause conflicts you would not get when doing it before. This will get you to something like:

A  -- master
|  B  -- work_branch
|  |
| /|
M  |     -- Merge work_branch to master.
|  |
C  |    -- New commit on master.
|  |
M' D     -- git revert M (undoes B) 
| /
F        -- git merge work_branch (You see changes from D, but not B)
|
M''   -- git revert M' (undoes M', you now see changes from B)

Upvotes: 0

gturri
gturri

Reputation: 14629

Let's say you have, after your merge

A -- B -- C -- F
 \            /L master
  \- D -- E--/
          L work_branch

If your commit B changes views.py, and if you didn't change it on work_branch, then it's normal that

  • You don't have a conflict on that file while merging
  • The file won't be the same on both branches (ie: between commits E and F)
  • There's no point in merging work_branch again, hence the Already up-to-date.

If you want master to be exactly like work_branch (ie: like commit E), you could do, at the root of your repo

git checkout master
git checkout work_branch -- .
git commit --all

Edit to follow-up on comment:

On the other hand, if you only changed views.py in commit E (ie: neither on B nor on C), then it seems quite strange that the file isn't the same on E and F.

If you didn't push / share your merge commit, you might want to retry the merge, in case an manipulation error occurred previously:

git checkout C
git branch -f master
git checkout master
git merge work_branch

Upvotes: 1

Ash Wilson
Ash Wilson

Reputation: 24478

git merge performs a three-way merge between the branch you're on and the branch you merge in. What this means is that, roughly, git:

  1. Identifies a common ancestor commit; the "nearest" commit that's shared by both master and work_branch;
  2. Generates a diff between that ancestor and master, and a diff between that ancestor and work_branch. These diffs describe the work that was done on each branch.
  3. Applies each diff from work_branch that doesn't conflict with one on master.

So, merging in a branch doesn't make the branch you're on identical to the one you merge in, it gives you a new state that has all of the work from both sides.

If what you actually want to do really is make one branch identical to another, you can (while you have master checked out):

  1. Use git checkout work_branch -- . in the top-level directory to make your working copy exactly the state it is in work_branch, and commit those changes. (You can also do this for individual paths or directories). This will create a new commit in master's existing history that introduces changes to make it identical. Or:
  2. Use git reset --hard work_branch while you're in master. This replaces master's history with work_branch's.

Upvotes: 0

Star Brilliant
Star Brilliant

Reputation: 3136

I assume that you are not familiar with the Git workflow.

You may have not committed in your work_branch. Make sure that you have committed your work in work_bench.

When you have resolved the conflicts, make sure that you did git add views.py before git commit or simply git commit with -a option (I always forget to do this)

If you assist that you did everything right, I think I need to know the log of your repo to see what has happened indeed.

Upvotes: 0

Related Questions