views:

96

answers:

6

I'm a git noob, and I know I'm missing something fundamental here. I've got three branches: master, feature1 and feature2. No two branch is identical, yet any attempt to merge from one branch to the other results in an "up-to-date" message. As you can imagine, I've done my work on feature1 and feature2, and now I just want to merge that work back into my master.

Here is what my current graph looks like:

*   c719e79 master
|\  
| * 3f38259 feature2
| * 4e2af8c
| * a6ee18c
| * 2339052
| * 2e31d49
| * 2586659
| * 8b4a194
| * 56200c1
| * 97598e3
| * c28bc8d
| * 68b2e2f
| * 1ad4ad8
| * 3d5f4ad
| * 83435ca
| * 4049428
| * 581134a
| * 6e5aa2d
* | 2c88093
|/  
* 3130ec9 feature1
* 54a5311 INITIAL COMMIT

Any ideas?


UPDATE

VonC - the explanation makes sense, but my git repo still doesn't. When I switch over to my master branch and then run "$ git diff --stat feature2", I get the following output:

$git diff --stat feature2
File1      |    2 +-
File2      |    6 +++---
File3      |    4 ++--
File4      |    2 +-
File5      |    2 +-
5 files changed, 8 insertions(+), 8 deletions(-)

I get an even longer list of files if I run the same command for feature1. So... I still have it telling me that I'm up-to-date, but the files in each branch are different.


UPDATE 2

@Scott - Okay, I think your response has helped clarify my problem a little. I understand that merging will not make all the branches identical, but will simply update the branch that I'm on.

However, it appears that my commits have gotten "out of order", or something. In other words, there are changes that exist on the feature2 branch that I want to appear on my master branch. Git must think that version of the files on my master branch are the "right" ones (whatever that means). How do I get Git to commit the differences on feature2 branch to my master branch when it thinks that the changes currently on master are the latest and greatest?


UPDATE 3 (final)

Well, I'm very grateful to all of you who tried to help me out. I figured out a work-around that solved it just as well, but I never actually figured out how to do what I had in mind.

After thinking through some of your comments, I did a rebase. The graph of the commit history was a straight line like you would expect. The trouble didn't go away, though: my feature2 branch was behind master by one commit, but it contained code that actually made it the branch with the "latest and greatest" code. Trying to merge the branches did nothing. Finally, I just decided to create a new branch off of my feature2 branch and called that "latest". So I guess, in the end, I'm grateful for how easy it is to branch with git. But it's clear that I'm missing something...

Thanks again, everyone.

A: 

Are you in the 'master' branch when you do the merge command?

git checkout master
git merge feature1
git merge feature2
ewall
A: 

You could check out branch master, make sure all your changes are committed, then try

git pull . feature1 feature2

But I'm not exactly a git expert myself, so I couldn't tell you with certainty what this will do. I mean, I know that it should merge feature1 and feature2 into master, but I can't guarantee that it will merge them exactly the way you want.

I'd advise backing up the repository first, just in case. Although I suppose you could always git reset --hard HEAD^ afterwards if something goes wrong.

David Zaslavsky
Backing up repository before doing merge would contradict the purpose of using vcs, don't you think?
Tomasz Zielinski
@Tomasz: No, not if you're learning how to use the VCS system and aren't confident that you know the right command to undo a mistake. Backing up the repository is absurdly simple (just use `cp -r`) and so is restoring (`rm -rf` and another `cp -r`) and it's pretty hard to screw that up. I usually do this when I'm trying out a new git command and it's paid off several times. (I hope you didn't downvote me for that...)
David Zaslavsky
Yes, `cp` is absurdly simple, and you might also use `diff a b > diff0001` and uninstall `git` completely. For purpose you mentioned there is absurdly simple `git clone`.
Tomasz Zielinski
@Tomasz: `git clone` sets the `origin` remote on the clone repository to refer to the original, which is not what you'd want in this case. Someone who's just getting used to git might not know that, or might not know what other side effects `git clone` may have, so it is not absurdly simple for them. On the same token I would not recommend `cp -r` to someone who is wholly unfamiliar with shell commands (although it's a heck of a lot easier to explain than `git clone`). Regarding your mention of `diff`: yes, that is exactly what someone might do before they learn to trust their VCS.
David Zaslavsky
A: 

The "Already up-to-date" does mean that one branch in ancestor of the other, all changes from one branch being already in the other.
From the git merge man page:

If all named commits are already ancestors of HEAD, git merge will exit early with the message "Already up-to-date."

Here the HEAD of feature1 is an ancestor of master (master has some new work made from feature1 HEAD).
So git merge feature1 will result in an "Already up-to-date" message.

As for feature2, your graph log shows it has been merged at some point in master.
Trying to redo the merge will also result in an "Already up-to-date".

VonC
I recalced your rep as per your request; you lost a whooping 24 rep :)
balpha
A: 

While on branch master, I'm using git merge feature1 and git merge feature2

What happened was IMO a so-called FF(Fast-Forward)-Merge.

From the MAN-Page:

git merge definition:

git-merge - Join two or more development histories together

What has happened:

FAST-FORWARD MERGE

Often the current branch head is an ancestor of the named commit. This is the most common case especially > when invoked from git pull: you are tracking an upstream repository, you have committed no local changes, > and now you want to update to a newer upstream revision. In this case, a new commit is not needed to store > the combined history; instead, the HEAD (along with the index) is updated to point at the named commit, without creating an extra merge commit.

This behavior can be suppressed with the --no-ff option.

(Source-Link)

Excursion: Additional information about branches

As branches are nothing more than just pointers to commits AND feature1 / feature2 are ancestors of master (as mentioned before), there is no reason to 'copy' the commits (and therefore the commits' history). It's more performant to just re-point the master-branch(-pointer) to the last commit.

Why is the master-branch-pointer then not on the 3f38259 commit?

I'm not quite sure here, but I think:

git merge feature1

has the auto-commit-option (explicit: --commit) turned on per default. So a commit is created. Plus, there is the 2c88093 commit in the master-branch, but not in the feature2-branch, which avoids putting the master-branch-pointer just to the 3f38259 feature2 commit to produce something like

3f38259 feature2 master(*)

If you would re-point your master to the 3f38259 branch explicitly , you would 'lose' the 2c88093 commit in your history.

bully
A: 

The problem is that you are expecting the feature1 and feature2 branches to change as well as master when you merge them in. However, merging only effects the branch you are currently on. If you want all three branches to point to the same commit snapshot, you can run

$ git checkout feature1
$ git merge master
$ git checkout feature2
$ git merge master

That will update feature1 and then feature2 to where master is - and you won't get any merge conflicts, since they are both direct ancestors of master.

The important point is: when you merge a branch into another branch, it only modifies the branch you are on (the one you are merging into) not the branch that you are merging in. In other words, if you are currently on your 'master' branch and you merge in 'feature1', it updates 'master' but not 'feature1'.

Scott Chacon
A: 

How do I get Git to commit the differences on feature2 branch to my master branch when it thinks that the changes currently on master are the latest and greatest?

maybe git rebase is what you are looking for? Link

bully