Re: `git diff`/`git apply` can generate/apply ambiguous hunks (ie. in the wrong place) (just like gnu diff/patch)
- From
Elijah Newren <newren@gmail.com>
- Date
- Jul 4, 2024, 20:07 UTC
- Message-ID
- <CABPp-BGVdQZCr=0NzY9vpUJqaH+5yxJdpvfUqqhtWB4V=nkwDw@mail.gmail.com>
- In-Reply-To
- <CAFjaU5sAVaNHZ0amPXJcbSvsnaijo+3X5Otg_Mntkx2GbikZMA@mail.gmail.com>
On Wed, Jul 3, 2024 at 8:25 AM Emanuel Czirai <correabuscar+gitML@gmail.com> wrote:
> > Subject: `git diff`/`git apply` can generate/apply ambiguous hunks (ie. in the wrong place) (just like gnu diff/patch)
Yes, this is already known. In fact, it was one of the big reasons we changed the default backend in rebase from apply to merge. From the git-rebase manpage:
```
Context
The apply backend works by creating a sequence of patches (by calling
format-patch internally), and then applying the patches in sequence
(calling am internally). Patches are composed of multiple hunks, each
with line numbers, a context region, and the actual changes. The line
numbers have to be taken with some fuzz, since the other side will
likely have inserted or deleted lines earlier in the file. The context
region is meant to help find how to adjust the line numbers in order to
apply the changes to the right lines. However, if multiple areas of the
code have the same surrounding lines of context, the wrong one can be
picked. There are real-world cases where this has caused commits to be
reapplied incorrectly with no conflicts reported. Setting diff.context
to a larger value may prevent such types of problems, but increases the
chance of spurious conflicts (since it will require more lines of
matching context to apply). The merge backend works with a full copy of each relevant file,
insulating it from these types of problems.
```> This doesn't affect `git rebase` as it's way more robust than simply > extracting the commits as patches and re-applying them. (I haven't looked > into `git merge` though, but I doubt it's affected)
This was not always true; and, in fact, rebase is actually still partially affected today -- if you pick the `apply` backend or pick arguments that imply that backend, then you can still run into this problem. The merge backend (the default) is unaffected, and this problem was one of the big reasons for us switching to make the merge backend the default instead of the apply backend.
git merge is unaffected.