wiki:GitRejectedPatch

Version 4 (modified by Piero Campalani, 11 years ago) ( diff )

add Alan's workflow from GitPatchDoesNotApply

Back to [ProvideFix How To Provide A Fix].

Dealing with rejected patches

It can often happen that a patch you submitted to the Patch Manager gets rejected by our benevolent dictator, especially if you're a new dev and you are not that familiar yet with the rasdaman coding guidelines.

In case you are not familiar with git neither, here's a couple of examples of possible solutions that apply to such situations.

SCENARIO: you formatted a patch pZ for commit Z in your local branch my_branch on top of A. The master branch is a clean and synced copy of the origin/master remote branch, hence the public HEAD of rasdaman:

  o-------o-------A-------B-------C  [master] -> [origin/master]
                   \
                    \   X--> rejected!
                     \ /-pZ
                      Z  [my_branch]

This is usually a recommended developing workflow, so if you worked directly on your local master, you might want to switch to this layout:

$ git stash
$ git checkout -b my_branch master
$ git checkout master
$ git fetch origin
$ git reset --hard origin/master
HEAD is now at `D' <ticket:XYZ - Brief description of this patch>
$ git branch
 * master
   tmp

Now the local master is synced with the patches that surely in the meantime were accepted in the Patch Manager. The other (local) branch my_branch contains your rejected commit Z.

At this point there can be possible solution in order to rework on the patch:

1. [Rebase &] amend

If there are not patches which were applied since your rejection (ie B and C, see above), you can avoid rebasing: your my_branch branch is still on top of origin's HEAD.

Otherwise firstly you can move my_branch on top of D:

  o-------o-------A-------B-------C  [master] -> [origin/master]
                   .               \
                    .               \
                     Z --(rebase)--> Z  [my_branch]

Afterwards, you can amend your commit: you can simply do it by modifying the files you are required to — also files not previously included in the Z commit, stage them, then re-commit with the --amend option. You also have the chance to change the title of your patch during the process, eg Z~

$ vim file1 file2 ... fileN
[do your stuff]
$ git add file1 file2 ... fileN
$ git commit --amend
[you can change the title here now through your configured $GIT_EDITOR]
  o-------o-------A-------B-------C  [master] -> [origin/master]
                                   \
                                    \
                                    Z~  [my_branch]

Now you can reformat the patch:

$ git format-patch HEAD~
0001-Z~.patch

Look out there are no other new patches in origin:

$ git fetch origin

Otherwise you can also try to see if your patch does not conflict with new ones: for instance while you were fixing your patch, a new one (D) was accepted:

  o-------o-------A-------B-------C-------D  [master] -> [origin/master]
                                   \
                                    \
                                    Z~  [my_branch]

Instead of re-rebasing, you can try:

$ git checkout master
$ git merge origin/master
$ git apply --check 0001-Z~.patch

If no output is printed, then you can submit the new patch: http://rasdaman.org/patchmanager.

2. Cherry-pick

An other possible solution, which might be easier in case your rejected patch has already been followed by tons of other patches you formatted and that were accepted, is cherry-picking.

For instance, a patch pZ (for your Z commit) was rejected, then a new patch from some other dev was accepted (B), and an other patch you developed afterwards on top of Z was accepted (patch pW for bringing local commit W to the public repo as W~):

  o-------o-------A-------B-------W~  [master] -> [origin/master]
                   \             /----> accepted
                    \   X-------/-----> rejected!
                     \ /-pZ    /-pW
                      Z-------W  [my_branch]

You can clone your master to a new branch and cherry-pick your Z but without creating a new Z commit, just taking its changes:

$ git checkout master
$ git fetch origin
$ git merge origin/master
$ git checkout -b my_other_branch master
$ # Pick Z (refs/heads/my_branch~):
$ git cherry-pick refs/heads/my_branch~ --no-commit
$ git status
[changes in Z are staged now]
  o-------o-------A-------B-------W~  [master] -> [origin/master]
                   \               \
                    \   o-(c-pick)-(Z~) [my_other_branch]
                     \ /
                      Z-------W  [my_branch]

This way you can now fix the changes, re-stage them and commit.


2A. Cherry-pick cleaning local master

Assuming (use export to set them in bash):

  rejcomm=sha-of-your-rejected-commit 
  lastgood=sha-before-your-rejected-commit 
#branch from last good commit
git checkout -b re-patch $lastgood

#cherry-pick rejected patch to be fixed, without committing it
git cherry-pick $rejcomm --no-commit

#Amend the files, stage them with git add, then commit and create the new patch
geany fileToAmend
git add fileToAmend
git commit -m "old message /vN" #with N=2 to be incremented just in case
git format-patch HEAD^ # Works only with single last commit

# Now you are left with the rejected patch still committed on the master
# and the "hopefully to be accepted" patch in your temporary branch
# A practical way to avoid merge conflicts and let you merge your branch
# and pull from master is to:

# Revert the rejected patch on your master
git checkout master
git revert $rejcomm

#merge your re-patch branch (should go without conflicts, if not see note)
git merge re-patch
  • NOTE: If you have more than one related commits (depending on) to the reverted patch (perhaps also to be amended), you can cherry pick also these to the branch and revert them in reverse order on the master.
  • NOTE2: Still not know what to do if the dependent commits are from other authors (should not happen since the patch was not accepted) but I guess the method still applies as long as you add a patch taking care of such dependent commits.

3. Brute force procedure

The following procedure ensures resolution even if you did not keep the patch branch in your local repo or would have a complex rebase due to subsequent local patches. Using a branch for each patch and rebasing it has to be preferred as a best workflow.

  • clone the repository from scratch (optional, also a new branch should do)
  • apply the patch manually (with --reject option)
  • git apply --reset patch_file
  • fix manually the rejected files
  • You can find them by their extension (.rej)
  • then generate a new patch

I think the only problem with this approach is that such patch won't be into your main working copy (existing repo), hence a clash might occur at next git pull.

Final note

Conflicts can always happen, it's not your fault.
https://duckduckgo.com/?q=git+rebase+conflict

Note: See TracWiki for help on using the wiki.