views:

87

answers:

3

My repository looks like:

X - Y- A - B - C - D - E             branch:master
     \                  \
      \                  \ merge master -> release
       \                  \
        M  ---  BCDE  ---  N         branch:release 

Here "M - BCDE - N" are manually (unfortunately!) applied changes approximately same as separate commits "A - B - C - D - E" (but seems GIT does not know that these changes are the same). I'd like to rebase and get the following structure:

X - Y- A - B - C - D - E     branch:master
                        \
                         *   branch:release 

I.e. I want to make branch:release to be exactly the same as branch:master and fork it from the master's HEAD.

But when I run "git rebase master" sitting at the branch release, GIT reports about lots of conflicts and refuces rebasing. How could I solve this?

Other explaination of this: I'd like to "re-create" branch:release from scratch from master's HEAD. And there are a lot of other people who had already made "git pull" for the branch:release, so I cannot use git reset + git push -f.

A: 

You could use git rebase -i master and remove the line for BCDE to discard that revision altogether. If it really is identical to A-B-C-D-E, then you shouldn't have a problem.

MikeSep
Though the OP asked about rebase, it's not actually an option, because people have already pulled the branch.
Jefromi
A: 

They are not LITERALLY identical, but - LOGICALLY identical. Changes may differ by, e.g., comments or unused files.

I executed sitting in branch:release:

$ git pull
$ git rebase -i master
<deleted all commits except the oldest one>
$ git diff
<oh, this is only an empty line addition, so it may be skipped>
$ git rebase --skip
Successfully rebased and updated refs/heads/release
$ git diff master
<nothing, ok!>
$ git diff origin/release
<lots of changes, ok!>
$ git push
 ! [rejected]        release -> release (non-fast-forward)
$ git pull
1 files changed, 1 insertions(+), 0 deletions(-)
$ git rebase release
<a lot of conflicts again! hmmm...>
$ git rebase --abort
$ gil log --graph
<and I see that nothing is really changed!>

Also note that lots of users used git push/pull for branch:release and branch:master, so I cannot rewrite commits in that branches.

You made a second account to post additional information which you could've just edited into your question (and really, this extra info isn't necessary).
Jefromi
I know. :-(Your registration interface is quite confusing. :-)
I WANTED to edit, but I couldn't, because I was already logged out from the account suddenly.
And I did not receive registration email with my password for the first account.
Oh! I restored my previous account via email.
Dmitry
Hmmm... Now I cannot bind this cookie-based account to my OpenID, because this OpenId is already bound to the second dmitry-kay account, and I cannot find how to remove the second account (dmitry-kay). So - I forget about the first account (Dmitry) and remain only the second one (dmitry-key), sorry.
Dmitry
@dmitry-kay, @Dmitry: It's probably be best if you accepted an answer as Dmitry just to get this off the unanswered questions list.
Jefromi
+1  A: 

You say that people have pulled the release branch already, so you can't reset. That also means you can't rebase - either way, you move the ref in a non-merge way, and upset everyone else.

Assuming that you want to throw away everything on the release branch (I'm a little confused by the M) and make it identical to master (why do you show the *?), here's what you can do:

git checkout master
git merge --strategy=ours release   # merge in release, but keep master's contents
git checkout release
git merge master                    # fast-forward

You'll end up with this:

X - Y- A - B - C - D - E ----- Z (master, release)
     \                  \     /
      \                  \   /
       \                  \ /
        M  ---  BCDE  ---  N

The merge commit Z will have discarded all changes from release; it's just there to ensure that release moves in a fast-forward. From the documentation:

ours

This resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. It is meant to be used to supersede old development history of side branches.

This is exactly your situation!

It's also not a bad idea to use the --no-commit option on the merge, then commit manually so that you get a chance to edit the message and note what you did.

Jefromi