Reputation: 532
We recently introduced gerrit to have a code review tool in our team. Now there is a question and I want to discuss my solution for that with you.
The problem: A developer is fixing some small bugs and want to use the code review for these changes. Because of issue IDs he is creating one change set for each bugfix. All the changes went to the branch "develop". In the meantime there is a reviewer and he has some doubts about some code changes. He (the verifier) asks the developer to change something on a specific change set (SHA 1234) which is not the last one.
The tree for the developer is at this time:
A <-- B <-- SHA1234 <-- D <-- E
Where A and B are commits already reviewed and submitted; SHA1234 is to be changed; D is a totally different patch set and already pushed to gerrit; E will be a totally different patch set (it is a commit that is not present in gerrit right now).
What to do now?
My proposed solution is something like that:
create a temporary branch
git branch tmp
reset head pointer to the commit to change SHA: 1234
git reset --hard 1234
do all the changes and commit after finishing with --amend
git commit --amend
rebase the "tmp" branch with remove the obsolete commit
git checkout tmp
git rebase -i develop
... remove the obsolete commit in the list and save+close the editor.
merge tmp back into develop and delete tmp branch
git checkout develop
git merge tmp
git branch -d tmp
push changes again to gerrit
git push origin HEAD:refs/for/develop
What do you think about? Is there a simpler solution/workflow?
Upvotes: 0
Views: 3005
Reputation: 43314
He asks the developer for a patch to a specific change set (SHA 1234) which is not the last one. What to do now?
Should be easy with gerrit, especially since he created a patch set for each bugfix.
First, because I have always used gerrit's "old screen" and have not yet found out how to do it with the "new screen", you might want to set yours to "old screen" as well.
In settings -> preferences -> change view
Then, on the page of the specific patch set your guy wants to retrieve, you should see this section
Here, he has a couple of options as you can see. checkout / pull / cherry-pick / patch. He can select the option he requires and then copy the link that appears and paste that in a git terminal.
I often use this for example to cherry-pick a new commit onto my local dev branch to verify some new code on an android device, because it's not always easy to see how and if it works by just looking at the code.
Edit:
The original developer has some further commits. So the tree has a dependency to sha1234. But he has to change sha1234 in order to apply the code review results. The commit that have sha1234 as the parent has to be rebased. Of course that has also impact of all the following commits he already have and result in some conflicts...
The initial question was: Is the proposed way (the steps above) to solve that situation wrong?
It's not necessarily wrong, but I feel there is an easier way.
Checkout the branch that has commit 1234 and the other commits that depend on it
Do an interactive rebase that goes back as far as commit 1234 is
$ git rebase -i HEAD~5 # replace 5 with how many commits back 1234 is
Set commit 1234 to 'edit' and the rest to 'pick' (pick should be the default). Exit nano/vim and confirm.
You will be brought back to commit 1234. Here you can make your edits and amend the commit. (note: amending a commit changes its hash)
$ git rebase --continue
git will now try to reapply the other commits on top of the amended 1234.
If no conflicts arise: great, you are now done rebasing.
If they do: solve the conflicts any way you like and mark the conflicts solved with git add or git rm. Then again git rebase --continue. Repeat this step until all conflicts are resolved. You should now be back at where you started, but with a changed history.
Now, since all those commits have been updated (1234 was amended, the others have an updated parent/dependency) you need to re-push them all to gerrit. This should be as simple as doing $ git push origin HEAD:refs/for/develop
and gerrit automatically detects which patch sets have received an update.
I explained this process in more detail here: Modifying old commit in git
Upvotes: 2