Reputation: 18242
I'm tracking an upstream fork, and have performed a git pull -s recursive -X theirs release master
to my local upstream
branch.
When I do git log release/master
I get a sha of 922371ba
, but when I do a git rev-parse HEAD
, I get a different sha, 03bebbf13
. What's the difference between these two?
I'm basically just trying to make sure my local commit matches the latest commit on release/master
.
Upvotes: 1
Views: 2643
Reputation: 45659
UPDATED - Question was updated to clarify that the command issued was not the command originally stated, and to state what OP is trying to accomplish. Some of the original answer still applies so I'm preserving it below, but here is the answer to the question as presently written:
git pull
can be configured to do a lot of things, but it always means "combine the changes from (the ref(s) I name) into my current commit line". Although -X theirs
will resolve all conflicts in favor of the changes you're pulling in, this will still keep any non-conflicting changes from the current branch.
In short, pull
is not what you want here.
OPTION 1 : If you want to just uproot upstream
and throw away its history, that's relatively easy.
git reset --hard release/master
Doing this is a history rewrite for upstream
, so two things:
First, if upstream
has been pushed previously, then it will now have to be force-pushed (git push --force-with-lease
).
Second, if anyone else has a copy of upstream
, the forced push will put them in a broken state. If they try an intuitive way to fix the problem the face, it may undo what you've done. To prevent that you have to coordinate with them and let them know what you're doing. See the git rebase
docs under "recovering from upstream rebase".
OPTION 2 : If you want upstream
to keep its current history, but you want the next commit on upstream
to have the same content as release/master
, there are several ways to do that. You should start with upstream
checked out and a clean working tree and index. Then make sure you have an up-to-date release/master
git fetch release
From there, a simple process (though it uses a less common command):
git reset --hard $(git commit-tree -p upstream -m "sync with release/master" release/master^{tree})
Or you could stick to more basic commands
git rm -r *
git checkout release/master -- .
git add .
git commit -m "sync with release/master"
At this point, future merges between this and release/master
will surely conflict, because git doesn't preserve any knowledge of the relationship between the branches' current state.
OPTION 2B : If you want to preserve the history of upstream
and/or can't cleanly coordinate the history rewrite, and if you nonetheless don't want to leave upstream
in a state where it's hard to interact with release/master
going forward, then you will want to create a merge commit between the two. That means the commit SHA for upstream
(which will be the merge commit) will still differ from the commit SHA for release/master
- BUT the content can be made to match, as you can verify with git diff
. To do this:
Follow the steps for OPTION 2 above. This will ensure that a default merge between origin/master
and upstream
would conflict. That's important because the next thing we're going to do is create what is sometimes called an "evil merge", and evil merges cause the most trouble if their parents could've merged cleanly using the default merge settings.
So now that you have the correct content on upstream
, we need to convince git that the branches are related.
git merge -s ours origin/master
Note that -s ours
is different from -x ours
. Here we're using the "ours merge strategy", which simply keeps the content exactly as we already have it. -X
would be an option (typically to the recursive strategy); in that case, a true content merge still occurs and only conflicts are settled in favor of our existing content.
Original Answer
We don't have enough information to do more than hopefully point you in the correct general direction... So here's what I can say with what's given:
When you say git pull release/master
, that means "fetch release/master
and merge it into my current branch (upstream
)[1].
This can result in one of two things: If the previous commit at the head of upstream
had been reachable (by parent pointers) from release/master
, then by default git would move upstream
to the same commit as release/master
.
If your configuration or options forbade a "fast-forward", or if the previous commit at the head of upstream
was not reachable (by parent pointers) from release/master
, then a new "merge commit" is created. This merge commit has two parents- the commit that was at the head of upstream
, and the commit from release/master
. It incorporates all changes from both.
It appears you're seeing the latter behavior. What the difference is depends on what changes had been made in upstream
that hand't been made in origin/master
(if any). You can tell what (if any) these are by git diff upstream origin/master
.
[1] Well, that's what it means by default. Your configuration could change that, for example by telling it to rebase your branch onto the fetch
ed commit instead of merging. I doubt that's what happened, but for the record that would also result in upstream
having a different commit hash from release/master
, and again you could see what's different with git diff
.
Upvotes: 3