Re: [RFH] "diff -B -M"

2015-02-06 Thread Junio C Hamano
Junio C Hamano  writes:

> 5. Third twist: rewriting by copying
> ...
> One possible way to fix this is to include another patch in the same
> patchset that shows the deletion of major-11.txt.  The rule 2. would
> be further revised to something like:
>
>  rule 2. a patch renaming file A to file B requires that file A
>  exists and file B does not exist in the target tree, unless
>  another patch in the patchset renames file B to some other
>  file (possibly but not necessarily file A) or removed file

Typofix: s/removed/removes/

>  B, in which case file B must appear in the target tree.
>
> Such a patchset would look like this:
>
> diff --git a/major-08.txt b/major-11.txt
> similarity index 97%
> rename from major-08.txt
> rename to major-11.txt
> ...
> diff --git a/major-11.txt b/major-11.txt
> deleted file mode 100644
> ...
>
> And these patches, under the re-revised rule 2. and rule 4., would
> apply cleanly to the old tree.
>
> What about the reverse application?  It would be a patchset that
> creates major-11.txt from nothingness, and creates major-08.txt by
> renaming major-11.txt and editing.  Is the rule 2. re-revised above
> sufficient?
>
> renaming major-11.txt to major-08.txt requires that major-08.txt
> does not exist in the target tree, unless...
>
> and the new tree (which is the target of the reverse application)
> only has major-11.txt and not major-08.txt, so this rename should go
> through.  The reverse of the deletion of major-11.txt is a creation
> of it with the contents fully given as the pre-image of the
> (original) patch before reversing it, so that should also be OK with
> rule 3.

... But rule 3. needs tweaking.  The second patch would be creating
major-11.txt which requires major-11.txt to be missing in the target
tree.  But obviously, the new tree the patch we are applying in
reverse was taken from has major-11.txt.  So we would need a
revision to it as well.

 rule 3. a patch that creates file A requires that file A does not exist
 in the target tree, unless another patch in the same patchset
 renames file A away or removes it.

> So tentatively, I would say...
>
>   Action item: do not filter delete-half of the broken pair
>   out, even when the other create-half of the pair no longer
>   is in the output.
>
>   Action item: update "git apply" to honor the rule 2.
>   re-revised above.

The latter should read:

update "git apply" to honor the revised rule 2. and 3.

--
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[RFH] "diff -B -M"

2015-02-06 Thread Junio C Hamano
I've been thinking about "diff -B -M" for quite a while, and I am
finding a few interesting problems we have in our codebase.  Here is
a snapshot, with a few action items.

In this write-up of my current thinking, I'll use these terms:

patchset::
Output from a single "git diff" invocation, which may contain
one or more "patch".

patch::
Part of a "patchset" from a line that begins with "diff --git"
up to (but excluding) the next line that begins with "diff --git".

tree::
"diff" compares two collections of files; each collection is a
"tree".  Left and right sides of the comparison are called "old
tree" and "new tree", respectively.  The "tree" we attempt to
apply a patchset is the "target tree".  The "tree" we would get
after successful application of a patchset is the "resulting
tree".  A "tree" does not have to be a tree object--we may be
comparing the index and the files in the working tree, for
example.

preimage::
postimage::
Lines in a "patch" that are prefixed by "-" or " " but not "+"
that denote what the patched file ought to have for the patchset
to apply ("preimage").  Lines with "+" or " " denote what the
patch result ought to look like ("postimage").


1. Basics

First the basics.  Let's think about a patchset with a single patch.
What does this patchset tell us?

diff --git a/major-08.txt b/major-08.txt
index 680c5f6..5de90cb 100644
--- a/major-08.txt
+++ b/major-08.txt
@@ -1,3 +1,3 @@
-8. Fortitude.
+8. Strength.

 This is one of the cardinal virtues, of which I shall speak later.

It obviously tells us that the new tree changed "Fortitude", that
used to be in the old tree, to "Strength", but it actually tells us
a bit more about the old tree.  For this patch to apply, the target
tree must have a file named "major-08.txt" that begins with lines we
see as the preimage in the patch.


2. Renaming a file

Now let's get a bit fancier and study a patchset with a rename
patch, which I invented very early in the Git's life (it was done
while Linus was still running the project).

What does this patchset tell us?

diff --git rws/major-08.txt marseille/major-11.txt
similarity index 97%
rename from major-08.txt
rename to major-11.txt
index 680c5f6..2ab22a0 100644
--- rws/major-08.txt
+++ marseille/major-11.txt
@@ -1,3 +1,3 @@
-8. Fortitude.
+11. Fortitude.

 This is one of the cardinal virtues, of which I shall speak later.

We can see that this is going from the same old tree as the previous
one's old tree, renames major-08.txt to major-11.txt with slight
modification.  It tells us a lot more about the trees, compared to
the previous example.  For this patchset to apply, the target tree
must satisfy the same preconditon as the previous one about
"major-08.txt", and in addition it must lack "major-11.txt";
otherwise we wouldn't be renaming a new file to it.  Also, it tells
us that the resulting tree must lack "major-08.txt".

So far, these are straight-forward.

In summary:

 rule 1. a patch from file A to file A means file A exists in the
 target tree with contents that match the preimage of the
 patch.  file A will be in the resulting tree.

 rule 2. a patch renaming file A to file B requires that file A
 exists the target tree with contents that match the
 preimage of the patch, and file B does not exist in the
 target tree. file A will not exist in the resulting tree.

 rule 3. a patch that creates file A requires that file A does not exist
 in the target tree.

 rule 4. a patch that deletes file A requires that file A exists in
 the target tree with contents that match the preimage of
 the patch.

The latter two I didn't illustrate with examples, but they should be
obvious.


3. First twist: cross renaming

Now, here is the first twist.  What does this patchset mean?

diff --git rws/major-11.txt marseille/major-08.txt
similarity index 99%
rename from major-11.txt
rename to major-08.txt
index 517d9f8..44e8d3a 100644
--- rws/major-11.txt
+++ marseille/major-08.txt
@@ -1,3 +1,3 @@
-11. Justice.
+8. La Justice

 That the Tarot, though it is of all reasonable antiquity, is not of
diff --git rws/major-08.txt marseille/major-11.txt
similarity index 97%
rename from major-08.txt
rename to major-11.txt
index 5de90cb..a101d5f 100644
--- rws/major-08.txt
+++ marseille/major-11.txt
@@ -1,3 +1,3 @@
-8. Strength.
+11. La Force

 This is one of the cardinal virtues, of which I shall speak later.

This is a "swap" patchset, that swaps major-08.txt and major-11.txt
with small edit.  You would have done something like this to prepare
it:

$ mv major-11.txt tmp
$ mv major-08.txt major-11.txt
$ mv tmp major-11.txt
$ edit major-08.txt major-11.txt ;# just a little
$ git commit -m swap major-08.txt major-11.txt