42

I've been using git-format-patch and git-am to apply changes from one repository to another. The file structures are the same but there are some changes in the repository I'm apply to which cause most patches to fail a few hunks. But most of the patch hunks apply with a little but of fuzzyness in the line numbers.

As far as I can tell git-am apply a very strict interpretation so rejects all these patches outright.

So my workflow has become

$ git am ../the-patch.patch
# Fails because the patch doesn't apply cleanly
$ patch -p1 < ../the-patch.patch
# Applies most of the hunks, leaves .rej files for the ones that conflict
# Fix the conflicting hunks manually
$ git am --continue

It would be nice if I didn't have to run the command line patch and could just have that happen as part of the am command.

Running with the --reject flag seems to create a .rej file with all the hunks in the file if any conflict, which isn't what I want.

Running with the --3way flag fails with

fatal: sha1 information is lacking or useless (the-file.java).
Repository lacks necessary blobs to fall back on 3-way merge.
Cannot fall back to three-way merge.

Which I presume is because the change set this was based on is not in the repository I'm merging to.

Is there any way to make git-am apply the patch with fuzzy matching like the raw patch command does and only create .rej files containing the hunks that failed?

CodeWizard
  • 128,036
  • 21
  • 144
  • 167
EdC
  • 2,309
  • 1
  • 17
  • 30
  • Seems useful and interesting. Can you provide a [sscce](http://sscce.org/) example to work with? I guess a repo with a first commit with file and patch and a second commit with expected results (applied hunks and .rej file) would be enough to investigate – albfan Jul 18 '15 at 21:01
  • @albfan Sorry, this question is so old, I'm struggling to even remember the original context, much less reproduce – EdC Jul 19 '15 at 22:23

6 Answers6

5

You can do the following:

git am /path/to/some.patch
patch -p1 < /path/to/some.patch
git add .
git am --continue

That would apply the patch and keep the commit message, etc.

César Izurieta
  • 413
  • 5
  • 10
  • 1
    Works great! so, patch command is your friend here. Be careful while using git add . - you may end up adding .orig files(so better add the corresponding files instead of . ) – kumar Jan 10 '19 at 12:55
2

How about:

git_apply-fuzzy() {
   if ! git am "$@"; then
      local patch="$(git rev-parse --show-toplevel)/.git/rebase-apply/patch"
      if [ -e "$patch" ] && patch --dry-run -p1 < "$patch"; then
          if patch -p1 < "$patch"; then
              sed -n -e '/^+++ b\//{s///;p}' "$patch" | xargs git add &&
              git am --continue &&
              return 0 ||
              patch -p1 -R < "$patch"
          fi
      fi
      git am --abort
      return 1
   fi
}
git_apply-fuzzy mypatch.patch

It tries 'git am' and, if it fails, try patch (reverting if anything strange happens)

1

If i understand you correctly you trying to merge code form 1 repo to another one and you are failing on some parts of your code. You then fix it manually and from now on you want it to be merged without any errors.

In this case you should use git rerere

In a workflow employing relatively long lived topic branches, the developer sometimes needs to resolve the same conflicts over and over again until the topic branches are done (either merged to the "release" branch, or sent out and accepted upstream).

This command assists the developer in this process by recording conflicted automerge results and corresponding hand resolve results on the initial manual merge, and applying previously recorded hand resolutions to their corresponding automerge results.

git config --global rerere.enabled true
Community
  • 1
  • 1
CodeWizard
  • 128,036
  • 21
  • 144
  • 167
1

Based on the thread that @Nick Desaulniers links to above, it looks like using the -3 option to git apply/am will work, at least to some extent.

For example, here's my output with a patch that failed with git apply:

$ git apply < patch_file.patch error: patch failed: file_being_patched.txt:489 error: file_being_patched.txt: patch does not apply $ git apply -3 < patch_file.patch error: patch failed: file_being_patched.txt:489 Falling back to three-way merge... Applied patch to 'file_being_patched.txt' cleanly.

It's a shame that it still gives an error (harder to parse output in scripts), and it doesn't say what the level of fuzz was the way that patch does, as the fuzz level is often a good indication of whether the patch command might have got it wrong.

joachim
  • 28,554
  • 13
  • 41
  • 44
0

This has the makings of a feature request. To become sure about that, join the Git mailing list (git@vger.kernel.org) and read it for a while to get a sense of the culture. At the same time clarify your thoughts by preparing before/after documentation as suggested above.

When you feel ready, then introduce yourself on the list and explain your idea consisely. Be sure to address the question of whether the effect of your proposal can be achieved adequately by other means. If you receive encouraging words, then follow up with your more detailed documentation. With feedback from your proposal in hand, you may decide to proceed with submitting a feature-request bug, or you may find youself in position to create a patch for consideration.

  • Thanks for the advice, I have emailed the mailing list. The thread can be tracked [here](https://marc.info/?l=git&m=148675446329323&w=2). – Nick Desaulniers Feb 10 '17 at 19:28
  • Since I can longer edit my comment (5 min limit), [here's](https://marc.info/?t=148675457100004&r=1&w=2) a link to the thread. – Nick Desaulniers Feb 10 '17 at 19:44
0

There is --recount parameter, but only for git-apply command, so theoretical sequence would be:

git mailsplit ...   
git mailinfo ...
git apply --recount ...
git add ...
git commit ...
radzimir
  • 1,178
  • 13
  • 10