{"thread":{"id":"19489","subject":"Git produces Unidiff - Does it really?","startedAt":"2009-05-24T23:15:43Z","lastAt":"2009-05-25T09:48:38Z","messageCount":3,"participants":["Jan Engelhardt","Junio C Hamano"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"114611","messageId":"alpine.LSU.2.00.0905250105410.22963@fbirervta.pbzchgretzou.qr","threadId":"19489","inReplyTo":null,"subject":"Git produces Unidiff - Does it really?","fromName":"Jan Engelhardt","fromEmail":"jengelh@medozas.de","sentAt":"2009-05-24T23:15:43Z","receivedAt":"2009-05-24T23:15:43Z","isPatch":false,"sender":{"key":"jengelh@medozas.de","avatar":null},"body":"Hi,\n\n\nso I noticed that the diff output generated by git tools, such as \n\"git diff\", \"git log -p\", etc. is not accepted by TortoiseSVN, but is \naccepted by patch(1). Now I wondered which program could be at fault.\nGit produces:\n\n\t--- a/src/foo.c\n\t+++ b/src/foo.c\n\t@@ your hunk goes here... @@\n\tetc.\n\nRandom webpages[1,2] have a tendency wanting to tell me unidiff is\n\n\t--- a/src/foo.c\t$TIMESTAMP\n\t+++ b/src/foo.c\t$TIMESTAMP\n\t@@ hunks... @@\n\ninstead, i.e. with the timestamp.\nSince the diff format is known to be sketchy (are there _any_ uptodate \nspecs that are actually followed?), which tool(s) is/are to blame?\n\n * git for not producing unidiff(-with-a-timestamp)\n * TSVN for not accepting unidiff(-without-a-timestamp)\n(* patch for accepting unidiff body together with a non-unidiff file \n   header)\n\n\nAny insights?\n\nJan\n"},{"id":"114620","messageId":"7v4ov9zwtt.fsf@alter.siamese.dyndns.org","threadId":"19489","inReplyTo":"alpine.LSU.2.00.0905250105410.22963@fbirervta.pbzchgretzou.qr","subject":"Re: Git produces Unidiff - Does it really?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-05-25T03:27:10Z","receivedAt":"2009-05-25T03:27:10Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jan Engelhardt <jengelh@medozas.de> writes:\n\n> Any insights?\n\nWe have \"index ...\" and other metainformation (most noticeable when\nrenames and mode changes are involved) before any hunk begins.  POSIX\nunified context format of course would not know about them either.\n\nIn the context of git, file modification time often does not have a\ndefined meaning.  If you are comparing two arbitrary tree objects (or two\narbitrary blob objects), there is no concept of \"timestamp of the preimage\nand the postimage\".  If you are comparing two commits, you _could_ show\nthe timestamps of the commits, but that is misleading and useless\ninformation.  The paths being shown may not have been changed by the newer\ncommit being compared, but by some other commit in-between the two commits\n(and even that is not guaranteed --- the two commits may not have any\nancestry relationship, and/or the clock of the committer who made one of\nthese commits may have had skews).\n\nThe enhancements and ommissions were chosen not to confuse tools that\npeople use to process patches.  The metainformation headers are safely\nignored by \"patch\", for example (of course \"patch\" does not know about\nrenames yet, but that can be fixed later).  Even though \"patch\" _can_\noptionally set the timestamp of the affected files, nobody sane would do\nso in the context of source code control (it will screw up \"make\").\n\nThe answer to your question depends on how anal you would want to be, but\nno, we fundamentally cannot produce \"unidiff -- _really_\" in the \"POSIX\nunified context format\" without losing useful information (renames and\nmodes) nor without adding information that is meaningless (timestamps).\n\nBut on the other hand, you can say what we produce is in unified context\nformat to the same extent that RCS and CVS produces unified when given -u\noption (i.e. \"rcsdiff -u\", \"cvs diff -u\").\n\nFor example, \"rcsdiff -u\" shows something like:\n\n    diff -u -r1.1 -r1.2\n    --- Make        1995/01/08 20:50:24     1.1\n    +++ Make        2001/10/04 07:14:29     1.2\n    @@ -1,7 +1,11 @@\n     #!/bin/sh\n    -...\n\nIt has cruft after the timestamp, and the timestamp itself is not even in\nthe format POSIX expects to see (see\n\n http://www.opengroup.org/onlinepubs/9699919799/utilities/diff.html#tag_20_34_10_07\n\nif you really care).\n\nIs it in violation of POSIX unified context format?  Of course yes.  Is it\nthen not in unified context format at all?\n\nFor all practical purposes, if you (either you human or your tool) know\nhow to read unified context format, you can process what we (or RCS)\nproduce.\n\nI used RCS as an example because it has been maintained by the same person\nwho maintains \"GNU diff\" and was one of the main player who pushed\n\"unified context\" format to the updated POSIX.\n"},{"id":"114647","messageId":"alpine.LSU.2.00.0905251117340.27529@fbirervta.pbzchgretzou.qr","threadId":"19489","inReplyTo":"7v4ov9zwtt.fsf@alter.siamese.dyndns.org","subject":"Re: Git produces Unidiff - Does it really?","fromName":"Jan Engelhardt","fromEmail":"jengelh@medozas.de","sentAt":"2009-05-25T09:48:38Z","receivedAt":"2009-05-25T09:48:38Z","isPatch":false,"sender":{"key":"jengelh@medozas.de","avatar":null},"body":"\nOn Monday 2009-05-25 05:27, Junio C Hamano wrote:\n>Jan Engelhardt writes:\n>\n>> Any insights?\n>\n>[...]\n>For example, \"rcsdiff -u\" shows something like:\n>\n>    diff -u -r1.1 -r1.2\n>    --- Make        1995/01/08 20:50:24     1.1\n>    +++ Make        2001/10/04 07:14:29     1.2\n>    @@ -1,7 +1,11 @@\n>     #!/bin/sh\n>    -...\n>It has cruft after the timestamp, and the timestamp itself is not even in\n>the format POSIX expects to see (see\n> http://www.opengroup.org/onlinepubs/9699919799/utilities/diff.html#tag_20_34_10_07\n>if you really care).\n>\n>Is it in violation of POSIX unified context format?  Of course yes.  Is it\n>then not in unified context format at all?\n>\n>For all practical purposes, if you (either you human or your tool) know\n>how to read unified context format, you can process what we (or RCS)\n>produce.\n>I used RCS as an example because it has been maintained by the same person\n>who maintains \"GNU diff\" and was one of the main player who pushed\n>\"unified context\" format to the updated POSIX.\n>\n\nHere is a random patch; not that I am fond of it, but it\nspeaks in code at least.\nTear it apar! :)\n\n\nparent 9619ff14159ab3401636b9883a715b0f20b051df (v1.6.3.1-152-g9619ff1)\ncommit 9d73395d1c08d2fc4e1b740c2d37d8daed7cb3e6\nAuthor: Jan Engelhardt <jengelh@medozas.de>\nDate:   Mon May 25 11:40:34 2009 +0200\n\ndiff: produce TSVN-acceptable diff\n\nOnce TortoiseSVNMerge sees a \\t after the filename in a --- line,\nit accepts a patch. (Not that t\nSo let's produce patches with said \\t, and a $ so the \\t does not\nget chopped off by incompetent tools or overlooked otherwise.\n---\n diff.c |    4 ++--\n 1 files changed, 2 insertions(+), 2 deletions(-)\n\ndiff --git a/diff.c b/diff.c\nindex f06876b..55cb974 100644\n--- a/diff.c\n+++ b/diff.c\n@@ -324,7 +324,7 @@ static void emit_rewrite_diff(const char *name_a,\n \tlc_a = count_lines(data_one, size_one);\n \tlc_b = count_lines(data_two, size_two);\n \tfprintf(o->file,\n-\t\t\"%s--- %s%s%s\\n%s+++ %s%s%s\\n%s@@ -\",\n+\t\t\"%s--- %s%s%s\\t$\\n%s+++ %s%s%s\\n%s@@ -\",\n \t\tmetainfo, a_name.buf, name_a_tab, reset,\n \t\tmetainfo, b_name.buf, name_b_tab, reset, fraginfo);\n \tprint_line_count(o->file, lc_a);\n@@ -637,7 +637,7 @@ static void fn_out_consume(void *priv, char *line, unsigned long len)\n \t\tname_a_tab = strchr(ecbdata->label_path[0], ' ') ? \"\\t\" : \"\";\n \t\tname_b_tab = strchr(ecbdata->label_path[1], ' ') ? \"\\t\" : \"\";\n \n-\t\tfprintf(ecbdata->file, \"%s--- %s%s%s\\n\",\n+\t\tfprintf(ecbdata->file, \"%s--- %s%s%s\\t$\\n\",\n \t\t\tmeta, ecbdata->label_path[0], reset, name_a_tab);\n \t\tfprintf(ecbdata->file, \"%s+++ %s%s%s\\n\",\n \t\t\tmeta, ecbdata->label_path[1], reset, name_b_tab);\n-- \n# Created with git-export-patch\n"}]}