threads / discuss / 4293

git-format-patch possible regressions

Subject: git-format-patch possible regressions

## tl;dr

14 messages between May 25, 2006 and May 28, 2006.

replies: 13people: 5as markdown or json

Marco Costalba· May 25, 2006, 19:23 UTC · lore
A couple of possible regressions:
1) Unreconized --signoff option

$ git --version git version 1.3.3.ged90 $ git-format-patch -s HEAD^..HEAD 0001-cat-file-document-p-option.txt $ git-format-patch --signoff HEAD^..HEAD fatal: unrecognized argument: --signoff

2) Unhandled ranges list

$ git --version git version 1.3.3.ged90 $ git-format-patch -s HEAD^..HEAD HEAD^^..HEAD^ 0001-cat-file-document-p-option.txt

$ git --version git version 1.3.3.gf205 git checkout -b test 51ce34b9923d9b119ac53414584f80e05520abea $ git-format-patch HEAD^..HEAD HEAD^^..HEAD^ 0001-Builtin-git-show-branch.txt 0002-Builtin-git-apply.txt

Both regressions brake qgit. The first one is easy to fix (--signoff --> -s) The second one is not so easy. It is use to format a patch series starting from a mouse selected multiple revisions. Note that the revisions could be not consecutive. Note also that looping git-format-patch for each revision does not updates patch number that always stay at 0001.

Feeding all the selected revisions in one go in the form git-format-patch sel1^..sel1 sel2^..sel2 ........ seln^..seln is the only way I have found to:

1) create a patch series of (randomly) selected revisions
2) increment patch numbers for each patch
   Marco
Linus Torvalds· May 25, 2006, 19:43 UTC · re: Marco Costalba · lore

Re: git-format-patch possible regressions

On Thu, 25 May 2006, Marco Costalba wrote:
> 
> 2) Unhandled ranges list
> 
> $ git-format-patch -s HEAD^..HEAD HEAD^^..HEAD^
You _really_ shouldn't use this "mix two ranges" format.
It may have "worked" before, but it
 - worked differently from all other git ranges
 - it was really an implementation detail (handling each argument 
   separately)

The "x..y" format is defined to mean the same thing "y ^x", and that means that "HEAD^..HEAD HEAD^^..HEAD^" really does mean the same thing as "^HEAD^ ^HEAD^^ HEAD HEAD^", which in turn means the same thing as "^HEAD^ HEAD" from a reachability standpoint (since HEAD^ is by definition reachable from HEAD, adding it won't change the revision list, and the same goes for ^HEAD^^ vs ^HEAD^).

So thus "HEAD^..HEAD HEAD^^..HEAD^" really _is_ the same thing as "HEAD^..HEAD", and any tool that thought otherwise was just being very confused.

Now, we could choose to try to make "a..b" mean something else (ie make the "^a" part only meaningful for that particular "sub-query"), and yes, in many ways that would be a more intuitive thing, but it's not how git revision descriptions work currently, and if we make that change we should do it across the board.

(It's not an easy change to make, but it should be possible by having multiple separate NECESSARY/UNNECESSARY bits, and make the revision walking logic a whole lot more complicated than it already is).

So I'd argue that you should really do something like
	( git-rev-list a..b ; git-rev-list c..d ) |
		git-format-patch --stdin
in qgit if you want the ranges to be truly independent.

(And no, I don't think git-format-patch takes a "--stdin" argument, but it might not be unreasonable to add it as a generic revision walking argument for scripting like this).

			Linus
Marco Costalba· May 25, 2006, 20:10 UTC · re: Linus Torvalds · lore

Re: git-format-patch possible regressions

On 5/25/06, Linus Torvalds <torvalds@osdl.org> wrote:
Show 13 quoted lines
>
>
> The "x..y" format is defined to mean the same thing "y ^x", and that means
> that "HEAD^..HEAD HEAD^^..HEAD^" really does mean the same thing as
> "^HEAD^ ^HEAD^^ HEAD HEAD^", which in turn means the same thing as "^HEAD^
> HEAD" from a reachability standpoint (since HEAD^ is by definition
> reachable from HEAD, adding it won't change the revision list, and the
> same goes for ^HEAD^^ vs ^HEAD^).
>
> So thus "HEAD^..HEAD HEAD^^..HEAD^" really _is_ the same thing as
> "HEAD^..HEAD", and any tool that thought otherwise was just being
> very confused.
>

Perhaps I have chose the wrong example but it was _only_ instrumental in better explaing the regression.

The general problem is how to format patches files named with consecutive numbers starting from a set of possible unrelated revisions.

Show 21 quoted lines
> Now, we could choose to try to make "a..b" mean something else (ie make
> the "^a" part only meaningful for that particular "sub-query"), and yes,
> in many ways that would be a more intuitive thing, but it's not how git
> revision descriptions work currently, and if we make that change we should
> do it across the board.
>
> (It's not an easy change to make, but it should be possible by having
> multiple separate NECESSARY/UNNECESSARY bits, and make the revision
> walking logic a whole lot more complicated than it already is).
>
> So I'd argue that you should really do something like
>
>         ( git-rev-list a..b ; git-rev-list c..d ) |
>                 git-format-patch --stdin
>
> in qgit if you want the ranges to be truly independent.
>
> (And no, I don't think git-format-patch takes a "--stdin" argument, but it
> might not be unreasonable to add it as a generic revision walking
> argument for scripting like this).
>

To fix qgit problem could be enough to add/modify the option -nx to make git-format-patch do not default with 0001 number but with x and then simply call git-format-patch in a loop:

    for(int i = 0;  i  <selectedRevisions.count(); i++)
         git-format patch -n<i+1> selectedRevisions[i]  ^selectedRevisions[i];

But of course it is clear your suggestion could be a solution for much broader cases.

    Marco
Junio C Hamano· May 25, 2006, 19:56 UTC · re: Marco Costalba · lore

Re: git-format-patch possible regressions

"Marco Costalba" <mcostalba@gmail.com> writes:
Show 12 quoted lines
> A couple of possible regressions:
>
> 1) Unreconized --signoff option
>
> $ git --version
> git version 1.3.3.ged90
> $ git-format-patch -s HEAD^..HEAD
> 0001-cat-file-document-p-option.txt
> $ git-format-patch --signoff HEAD^..HEAD
> fatal: unrecognized argument: --signoff
>...
> Both regressions brake qgit. The first one is easy to fix (--signoff  --> -s)

I do not think -s does what you want. It means "do not generate diff" to the diff family, but format-patch overrides it and forces generating patch+stat output, so you do not see what it is doing.

Also I do not think we would want to have --sign to format-patch anyway; it encourages a wrong workflow. Please see this and other messages in the thread:

	http://article.gmane.org/gmane.comp.version-control.git/20389

On a slightly related topic, I sent a message to Pasky about this -s stuff. It means something slightly different in diff-files (instead of asking for no output, it behaves as a no-op there), and we can remove that compatibility wart once Cogito stops using "diff-files -s" when it wants to do "diff-files" in cg-merge (and I suspect that diff-files is unnecessary).

> 2) Unhandled ranges list
>
> The second one is not so easy.

This is a real regression; I was hoping Porcelain writers were paying attention of what are coming, but obviously the description in "What's in git.git" messages and discussion on the list were not detailed enough. My apologies.

Having said that, I think what Linus says about equilvalence between "a..b" and "^a b" makes whole lot of sense. However, I could argue both ways. Linus's interpretation of "a..b c..d" is "^a ^c b d", but format-patch's interpretation has always been "do '^a b' and then '^c d'".

The former is more generic; you could say "not in A nor B but in C pretty easily -- list of ranges cannot express something like that. On the other hand, at least in the context of usual format-patch, the convenience of being able to work on more than one ranges in sequence may far outweigh the restriction of not being able to say something like that.

As an easy alternative, we could give --start-number=<n> to format-patch so that you can do the iteration yourself instead of having format-patch to iterate over the list.

Marco Costalba· May 25, 2006, 20:21 UTC · re: Junio C Hamano · lore

Re: git-format-patch possible regressions

Show 7 quoted lines
> > Both regressions brake qgit. The first one is easy to fix (--signoff  --> -s)
>
> I do not think -s does what you want.  It means "do not generate
> diff" to the diff family, but format-patch overrides it and
> forces generating patch+stat output, so you do not see what it
> is doing.
>
Sorry, I was fooled by git-format-patch.txt documentation.
Show 9 quoted lines
> > 2) Unhandled ranges list
> >
> > The second one is not so easy.
>
> This is a real regression; I was hoping Porcelain writers were
> paying attention of what are coming, but obviously the
> description in "What's in git.git" messages and discussion on
> the list were not detailed enough.  My apologies.
>

Sorry also for this, normally I read "What's in git.git" but perhaps I missed this.

Show 6 quoted lines
>
> As an easy alternative, we could give --start-number=<n> to
> format-patch so that you can do the iteration yourself instead
> of having format-patch to iterate over the list.
>
>
You beat me for few minutes ;-)
     Marco
Johannes Schindelin· May 25, 2006, 21:55 UTC · re: Junio C Hamano · lore

Re: git-format-patch possible regressions

Hi,
On Thu, 25 May 2006, Junio C Hamano wrote:
Show 7 quoted lines
> "Marco Costalba" <mcostalba@gmail.com> writes:
> 
> > 2) Unhandled ranges list
> >
> > The second one is not so easy.
> 
> This is a real regression;

I was not aware of the possibility to specify several ranges, mostly because I did not use it that way.

However, I think it is worth breaking this in that particular case, since the range handling has become unified with the framework in revision.[ch]

> As an easy alternative, we could give --start-number=<n> to
> format-patch so that you can do the iteration yourself instead
> of having format-patch to iterate over the list.
Something like this?

--- [PATCH] format-patch: support --start-number=<n> (and --start-number <n>)

This option implicitely sets numbered mode and starts the numbering with <n>.
Signed-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>
---
 builtin-log.c |   19 ++++++++++++++++---
 1 files changed, 16 insertions(+), 3 deletions(-)
diff --git a/builtin-log.c b/builtin-log.c
index c8feb0f..4e3388b 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -148,6 +148,7 @@ int cmd_format_patch(int argc, const cha
 	int nr = 0, total, i, j;
 	int use_stdout = 0;
 	int numbered = 0;
+	int start_number = -1;
 	int keep_subject = 0;
 
 	init_revisions(&rev);
@@ -171,7 +172,14 @@ int cmd_format_patch(int argc, const cha
 		else if (!strcmp(argv[i], "-n") ||
 				!strcmp(argv[i], "--numbered"))
 			numbered = 1;
-		else if (!strcmp(argv[i], "-k") ||
+		else if (!strncmp(argv[i], "--start-number=", 15))
+			start_number = strtol(argv[i] + 15, NULL, 10);
+		else if (!strcmp(argv[i], "--start-number")) {
+			i++;
+			if (i == argc)
+				die("Need a number for --start-number");
+			start_number = strtol(argv[i], NULL, 10);
+		} else if (!strcmp(argv[i], "-k") ||
 				!strcmp(argv[i], "--keep-subject")) {
 			keep_subject = 1;
 			rev.total = -1;
@@ -193,6 +201,11 @@ int cmd_format_patch(int argc, const cha
 	}
 	argc = j;
 
+	if (start_number >= 0)
+		numbered = 1;
+	else if (numbered)
+		start_number = 1;
+
 	if (numbered && keep_subject < 0)
 		die ("-n and -k are mutually exclusive.");
 
@@ -219,11 +232,11 @@ int cmd_format_patch(int argc, const cha
 	}
 	total = nr;
 	if (numbered)
-		rev.total = total;
+		rev.total = total + start_number - 1;
 	while (0 <= --nr) {
 		int shown;
 		commit = list[nr];
-		rev.nr = total - nr;
+		rev.nr = rev.total - nr;
 		if (!use_stdout)
 			reopen_stdout(commit, rev.nr, keep_subject);
 		shown = log_tree_commit(&rev, commit);
-- 
1.3.3.gd515
Johannes Schindelin· May 25, 2006, 22:18 UTC · re: Johannes Schindelin · lore

Re: git-format-patch possible regressions

Hi,
On Thu, 25 May 2006, Johannes Schindelin wrote:
Show 12 quoted lines
> @@ -193,6 +201,11 @@ int cmd_format_patch(int argc, const cha
>  	}
>  	argc = j;
>  
> +	if (start_number >= 0)
> +		numbered = 1;
> +	else if (numbered)
> +		start_number = 1;
> +
>  	if (numbered && keep_subject < 0)
>  		die ("-n and -k are mutually exclusive.");
>  
Thinking about this again, it makes more sense not to imply --numbered:
	if (numbered && start_number < 0)
		start_number = 1;

Ciao, Dscho

Junio C Hamano· May 25, 2006, 23:11 UTC · re: Johannes Schindelin · lore

Re: git-format-patch possible regressions

Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> Thinking about this again, it makes more sense not to imply --numbered:

Yes, that makes sense. That way you can say "Please start naming the output files at 0032-xxxx.txt, because you gave me 31 patch series last time, but I do not want [PATCH x/y] on the subject line, just [PATCH]".

That brings up another issue. Don't we need to have another option --total-number that overrides the /y part above?

Hmm...
Johannes Schindelin· May 25, 2006, 23:28 UTC · re: Junio C Hamano · lore

Re: git-format-patch possible regressions

Hi,
On Thu, 25 May 2006, Junio C Hamano wrote:
Show 11 quoted lines
> Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> 
> > Thinking about this again, it makes more sense not to imply --numbered:
> 
> Yes, that makes sense.  That way you can say "Please start
> naming the output files at 0032-xxxx.txt, because you gave me 31
> patch series last time, but I do not want [PATCH x/y] on the
> subject line, just [PATCH]".
> 
> That brings up another issue.  Don't we need to have another
> option --total-number that overrides the /y part above?

I thought about that, too. Isn't the --numbered only useful for submitting a patch series via mail? And isn't it necessary to make certain that these patches really apply in that order? Isn't it then sensible to force the user to have a branch (at least a throw-away one) having exactly these patches, just to make sure that the patches really, really apply in that order?

If all that is true, then --start-number && --numbered does not make sense at all.

Ciao, Dscho

Marco Costalba· May 26, 2006, 06:09 UTC · re: Johannes Schindelin · lore

Re: git-format-patch possible regressions

On 5/26/06, Johannes Schindelin <Johannes.Schindelin@gmx.de> wrote:
Show 26 quoted lines
> Hi,
>
> On Thu, 25 May 2006, Junio C Hamano wrote:
>
> > Johannes Schindelin <Johannes.Schindelin@gmx.de> writes:
> >
> > > Thinking about this again, it makes more sense not to imply --numbered:
> >
> > Yes, that makes sense.  That way you can say "Please start
> > naming the output files at 0032-xxxx.txt, because you gave me 31
> > patch series last time, but I do not want [PATCH x/y] on the
> > subject line, just [PATCH]".
> >
> > That brings up another issue.  Don't we need to have another
> > option --total-number that overrides the /y part above?
>
> I thought about that, too. Isn't the --numbered only useful for submitting
> a patch series via mail? And isn't it necessary to make certain that these
> patches really apply in that order? Isn't it then sensible to force the
> user to have a branch (at least a throw-away one) having exactly these
> patches, just to make sure that the patches really, really apply in that
> order?
>
> If all that is true, then --start-number && --numbered does not make sense
> at all.
>

I was thinking, probably wrong, that the number prepended in file name is used also to disambiguate two patches with the same subject.

     Marco
Junio C Hamano· May 26, 2006, 06:16 UTC · re: Marco Costalba · lore

Re: git-format-patch possible regressions

"Marco Costalba" <mcostalba@gmail.com> writes:
> I was thinking, probably wrong, that the number prepended in file name
> is used also to disambiguate two patches with the same subject.

What Johannes and I were discussing was the other number -- the total in the series. IOW, y in "[PATCH x/y]". OTOH, the number used for disambiguation you care about is x, which is made adjustable with --start-number patch.

So the way for qgit to use it would become something like this. Instead of giving a list of ranges like "a..b c..d e..f":

 * Run "format-patch a..b"; by reading from its stdout you know
   what patches you got -- you count them.
 * Run "format-patch --start-number=6 c..d" (if you got 5 out of
   a..b);
 * Run "format-patch --start-number=n e..f" (now you know the drill).

Then the sequence out of c..d would start with a file 0006-xxxx.txt, which is what you want for disambiguation.

Jakub Narebski· May 26, 2006, 06:26 UTC · re: Junio C Hamano · lore

Re: git-format-patch possible regressions

Junio C Hamano wrote:
Show 8 quoted lines
> So the way for qgit to use it would become something like this.
> Instead of giving a list of ranges like "a..b c..d e..f":
> 
>  * Run "format-patch a..b"; by reading from its stdout you know
>    what patches you got -- you count them.
> 
>  * Run "format-patch --start-number=6 c..d" (if you got 5 out of
>    a..b);
[...]

I still think that having _shortcut notation_ being different for very different commands is not a bad idea.

If one is really concerned about consistency of rev-list options, we could use ',' or something to separate separate lists of commits, e.g.

   git format-patch a..b , c..d , e..f
or
   git format-patch a..b --then c..d --then e..f
What do you think about the idea?
-- 
Jakub Narebski
Warsaw, Poland
Marco Costalba· May 27, 2006, 09:12 UTC · re: Junio C Hamano · lore

Re: git-format-patch possible regressions

On 5/26/06, Junio C Hamano <junkio@cox.net> wrote:
Show 6 quoted lines
>
> What Johannes and I were discussing was the other number -- the
> total in the series.  IOW, y in "[PATCH x/y]".  OTOH, the number
> used for disambiguation you care about is x, which is made
> adjustable with --start-number patch.
>
New --start-number patch says:

"Since the "a..b c..d" syntax is interpreted as "b ^a d ^c" as other range-ish commands, if you want to format a..b and then c..d and end up with files consecutively numbered, the second run needs to be able to tell the command what number to start from.

This does not imply --numbered (which gives [PATCH n/m] to the subject)."
Actually it seems that --numbered is needed anyway.

$ git-format-patch HEAD^..HEAD 0000-git-format-patch-start-number-n.txt $ git-format-patch --start-number=7 HEAD^..HEAD 0000-git-format-patch-start-number-n.txt $ git-format-patch --numbered --start-number=7 HEAD^..HEAD 0007-git-format-patch-start-number-n.txt

But with numbered also the patch subject is changed with added [PATCH n/m] that is not needed.

Also mutually exclusive check is not performed git-format-patch -n -k HEAD^..HEAD 0001-git-format-patch-start-number-n.txt

This patch should fix all.
Subject: [PATCH] Let git-format-patch --start-number option to work
also without --numbered
While there also fix the check for mutually exclusive -n and -k option
Signed-off-by: Marco Costalba <mcostalba@gmail.com>
---
 builtin-log.c |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)
diff --git a/builtin-log.c b/builtin-log.c
index 71f4ff9..c35733f 100644
--- a/builtin-log.c
+++ b/builtin-log.c
@@ -148,7 +148,7 @@ int cmd_format_patch(int argc, const cha
 	int nr = 0, total, i, j;
 	int use_stdout = 0;
 	int numbered = 0;
-	int start_number = -1;
+	int start_number = 0;
 	int keep_subject = 0;

 	init_revisions(&rev);
@@ -201,9 +201,9 @@ int cmd_format_patch(int argc, const cha
 	}
 	argc = j;

-	if (numbered && start_number < 0)
+	if (numbered && start_number == 0)
 		start_number = 1;
-	if (numbered && keep_subject < 0)
+	if (numbered && keep_subject)
 		die ("-n and -k are mutually exclusive.");

 	argc = setup_revisions(argc, argv, &rev, "HEAD");
@@ -233,7 +233,7 @@ int cmd_format_patch(int argc, const cha
 	while (0 <= --nr) {
 		int shown;
 		commit = list[nr];
-		rev.nr = rev.total - nr;
+		rev.nr = start_number + total - nr - 1;
 		if (!use_stdout)
 			reopen_stdout(commit, rev.nr, keep_subject);
 		shown = log_tree_commit(&rev, commit);
-- 
1.3.3.gfa0f-dirty

← back to recent threads