0

Given the initial state:

A - origin/branch-1
|
X   A - origin/branch-2
| /
M - master

where both A commits make the same edit and where it has no overlap with the X commit, what is the best way to get things to the following state?:

A - origin/branch-1 - origin/branch-2
|
X
|
M - master

Specifically, I want to NOT end up in the following state as (regardless of the physical actions taken) the logical actions are sequential and do not include a merge (i.e. the state where A didn't follow X was never valid in the first place and should be removed from the repository):

M - origin/branch-1 - origin/branch-2
|  \
A   |
|   |
X   A
| /
M - master
BCS
  • 75,627
  • 68
  • 187
  • 294

1 Answers1

0

A remote-tracking name like origin/branch-1 or origin/branch-2 represents your Git's memory of some other Git's branch name. That is, your Git called up their Git; their Git said my branch-2 holds hash ID _____ (fill in the blank with an actual hash ID) and your Git then grabbed that commit if necessary, so that you have it, and created or updated your origin/branch-2 to point to that commit.

Assuming that A and A are really A and A'—i.e., two different commits with different hash IDs but similar effects), your job is to convince the other Git repository—the one over on origin—to set its branch name branch2 to point to whichever of these two is the desired hash. You have that hash ID in your Git under the name origin/branch-1, so:

git push --force origin origin/branch-1:branch-2

will have your Git call up the Git at origin and tell it: I don't care which commit your branch2 identifies right now, make it point to hash ID _____ right now! (with the blank here filled in with the hash ID your Git has stored under the name origin/branch-1).

They may obey this command, or they may not. If they don't, you can't fix it from here like this: you will have to get someone who can issue such commands, to do that. That someone might be yourself but logged in to the server directly, or it might be someone with administrative permissions.1

Suppose they do obey. Their branch-2 currently points to some commit—maybe the one you think, maybe some other commit that's been added since then. Either way, though, they obey your forceful command, and now their branch-2 points to the other A. Your Git sees that they did obey, and updates your origin/branch-2, and you get what you wanted.

Be careful with force-push operations. Note that you can use --force-with-lease but to do so you'll need to create a local branch name on your end. The --force-with-lease operation needs to know what hash ID to hand to them, as it changes the command from I don't care, set to ___ to I think your branch is currently ___; if so, set it to ___; either way, tell me if I was right and if you obeyed. To make all this work, your Git you to have your own local name branch-2 that it can map back to your local origin/branch-2 so that it can get the hash IDs for both blanks.


1As a subterfuge, sometimes if you can't convince another Git to update a branch name, you can just tell that other Git to delete the branch name entirely. Having deleted it, you can then tell that other Git to create a whole new, totally different branch name that merely happens to have the exact same spelling. A lot of times, a Git that won't let you force-update a branch name, will let you delete and re-create it however you like.

torek
  • 448,244
  • 59
  • 642
  • 775
  • What effect would delete/re-create normally have on active PRs/MRs? --- Aside: I'm starting to thing that the fundamental flaw in Git is that it refuses to admit that source-history, code-review and development-history are fundamentally different processes (regardless of there superficial similarities) and need to be treated as such. – BCS Mar 24 '20 at 22:15
  • I don't know: I have not done it on GitHub. (I assume by "PR" you mean GitHub Pull Request. Every host with a pull request system has its own peculiarities as Git itself has nothing equivalent. The one built in is `git request-pull` which merely generates an email message.) – torek Mar 24 '20 at 23:24
  • Also: I have not used Gerrit but I understand it has its own separate ID for reviews. When using Git underneath it, you paste the Gerrit ID into each commit, so that reviewing is completely independent of eventual committing. – torek Mar 24 '20 at 23:25