{"thread":{"id":"841","subject":"[PATCH] Documentation: describe diff tweaking.","startedAt":"2005-06-05T21:30:58Z","lastAt":"2005-06-06T00:54:10Z","messageCount":2,"participants":["Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"4609","messageId":"7vr7fg1ofh.fsf@assigned-by-dhcp.cox.net","threadId":"841","inReplyTo":null,"subject":"[PATCH] Documentation: describe diff tweaking.","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-05T21:30:58Z","receivedAt":"2005-06-05T21:30:58Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"This adds documentation for the diffcore mechanism and explains\nhow numeric parameters to -B/-C/-M options affect the output,\nwhich was left \"black magic\" so far.\n\nThe documentation is not connected to any of the other asciidoc\nnodes yet.  Awaiting for suggestions, fixes and help from other\npeople.\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\n\n Documentation/diffcore.txt |  241 ++++++++++++++++++++++++++++++++++++++++++++\n 1 files changed, 241 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/diffcore.txt b/Documentation/diffcore.txt\nnew file mode 100644\n--- /dev/null\n+++ b/Documentation/diffcore.txt\n@@ -0,0 +1,241 @@\n+Tweaking diff output\n+====================\n+June 2005\n+\n+\n+Introduction\n+------------\n+\n+The diff commands git-diff-cache, git-diff-files, and\n+git-diff-tree can be told to manipulate differences they find\n+in unconventional ways before showing diff(1) output.  The\n+manipulation is collectively called \"diffcore transformation\".\n+This short note describes what they are and how to use them to\n+produce diff outputs that are easier to understand than the\n+conventional kind.\n+\n+\n+The chain of operation\n+----------------------\n+\n+The git-diff-* family works by first comparing two sets of\n+files:\n+\n+ - git-diff-cache compares contents of a \"tree\" object and the\n+   working directory (when --cached flag is not used) or a\n+   \"tree\" object and the index file (when --cached flag is\n+   used);\n+\n+ - git-diff-files compares contents of the index file and the\n+   working directory;\n+\n+ - git-diff-tree compares contents of two \"tree\" objects.\n+\n+In all of these cases, the commands themselves compare\n+corresponding paths in the two sets of files.  The result of\n+comparison is passed from these commands to what is internally\n+called \"diffcore\", in a format similar to what is output when\n+the -p option is not used.  E.g.\n+\n+    in-place edit  :100644 100644 bcd1234... 0123456... M file0\n+    create         :000000 100644 0000000... 1234567... N file4\n+    delete         :100644 000000 1234567... 0000000... D file5\n+    unmerged       :000000 000000 0000000... 0000000... U file6\n+\n+The diffcore mechanism is fed a list of such comparison results\n+(each of which is called \"filepair\", although at this point each\n+of them talks about a single file), and transforms such a list\n+into another list.  There are currently 7 such transformations:\n+\n+ - diffcore-pathspec\n+ - diffcore-break\n+ - diffcore-rename\n+ - diffcore-merge-broken\n+ - diffcore-pickaxe\n+ - diffcore-order\n+\n+These are applied in sequence.  The set of filepairs git-diff-*\n+commands find are used as the input to diffcore-pathspec, and\n+the output from diffcore-pathspec is used as the input to the\n+next transformation.  The final result is then passed to the\n+output routine and generates either diff-raw format (see Output\n+format sections of the manual for git-diff-* commands) or\n+diff-patch format.\n+\n+\n+diffcore-pathspec\n+-----------------\n+\n+The first transformation in the chain is diffcore-pathspec, and\n+is controlled by giving the pathname parameters to the\n+git-diff-* commands on the command line.  The pathspec is used\n+to limit the world diff operates in.  It removes the filepairs\n+outside the specified set of pathnames.\n+\n+Implementation note.  For performance reasons, git-diff-tree\n+uses the pathname parameters on the command line to cull set of\n+filepairs it feeds the diffcore mechanism itself, and does not\n+use diffcore-pathspec, but the end result is the same.\n+\n+\n+diffcore-break\n+--------------\n+\n+The second transformation in the chain is diffcore-break, and is\n+controlled by the -B option to the git-diff-* commands.  This is\n+used to detect a filepair that represents \"complete rewrite\" and\n+break such filepair into two filepairs that represent delete and\n+create.  E.g.  If the input contained this filepair:\n+\n+    :100644 100644 bcd1234... 0123456... M file0\n+\n+and if it detects that the file \"file0\" is completely rewritten,\n+it changes it to:\n+\n+    :100644 000000 bcd1234... 0000000... D file0\n+    :000000 100644 0000000... 0123456... N file0\n+\n+For the purpose of breaking a filepair, diffcore-break examines\n+the extent of changes between the contents of the files before\n+and after modification (i.e. the contents that have \"bcd1234...\"\n+and \"0123456...\" as their SHA1 content ID, in the above\n+example).  The amount of deletion of original contents and\n+insertion of new material are added together, and if it exceeds\n+the \"break score\", the filepair is broken into two.  The break\n+score defaults to 50% of the size of the smaller of the original\n+and the result (i.e. if the edit shrinks the file, the size of\n+the result is used; if the edit lengthens the file, the size of\n+the original is used), and can be customized by giving a number\n+after \"-B\" option (e.g. \"-B75\" to tell it to use 75%).\n+\n+\n+diffcore-rename\n+---------------\n+\n+This transformation is used to detect renames and copies, and is\n+controlled by the -M option (to detect renames) and the -C option\n+(to detect copies as well) to the git-diff-* commands.  If the\n+input contained these filepairs:\n+\n+    :100644 000000 0123456... 0000000... D fileX\n+    :000000 100644 0000000... 0123456... N file0\n+\n+and the contents of the deleted file fileX is similar enough to\n+the contents of the created file file0, then rename detection\n+merges these filepairs and creates:\n+\n+    :100644 100644 0123456... 0123456... R100 fileX file0\n+\n+When the \"-C\" option is used, the original contents of modified\n+files and contents of unchanged files are considered as\n+candidates of the source files in rename/copy operation, in\n+addition to the deleted files.  If the input were like these\n+filepairs, that talk about a modified file fileY and a newly\n+created file file0:\n+\n+    :100644 100644 0123456... 1234567... M fileY\n+    :000000 100644 0000000... 0123456... N file0\n+\n+the original contents of fileY and the resulting contents of\n+file0 are compared, and if they are similar enough, they are\n+changed to:\n+\n+    :100644 100644 0123456... 1234567... M fileY\n+    :100644 100644 0123456... 0123456... C100 fileY file0\n+\n+In both rename and copy detection, the same \"extent of changes\"\n+algorithm used in diffcore-break is used to determine if two\n+files are \"similar enough\", and can be customized to use\n+similarity score different from the default 50% by giving a\n+number after \"-M\" or \"-C\" option (e.g. \"-M8\" to tell it to use\n+8/10 = 80%).\n+\n+Note.  When the \"-C\" option is used, git-diff-cache and\n+git-diff-file commands feed not just modified filepairs but\n+unmodified ones to diffcore mechanism as well.  This lets the\n+copy detector consider unmodified files as copy source\n+candidates at the expense of making it slower.  Currently\n+git-diff-tree does not feed unmodified filepairs even when the\n+\"-C\" option is used, so it can detect copies only if the file\n+that was copied happened to have been modified in the same\n+changeset.\n+\n+\n+diffcore-merge-broken\n+---------------------\n+\n+This transformation is used to merge filepairs broken by\n+diffcore-break, and were not transformed into rename/copy by\n+diffcore-rename, back into a single modification.  This always\n+runs when diffcore-break is used.\n+\n+For the purpose of merging broken filepairs back, it uses a\n+different \"extent of changes\" computation from the ones used by\n+diffcore-break and diffcore-rename.  It counts only the deletion\n+from the original, and does not count insertion.  If you removed\n+only 10 lines from a 100-line document, even if you added 910\n+new lines to make a new 1000-line document, you did not do a\n+complete rewrite.  diffcore-break breaks such a case in order to\n+help diffcore-rename to consider such filepairs as candidate of\n+rename/copy detection, but if filepairs broken that way were not\n+matched with other filepairs to create rename/copy, then this\n+transformation merges them back into the original\n+\"modification\".\n+\n+The \"extent of changes\" parameter can be tweaked from the\n+default 80% (that is, unless more than 80% of the original\n+material is deleted, the broken pairs are merged back into a\n+single modification) by giving a second number to -B option,\n+like these:\n+\n+\t-B50/60 (give 50% \"break score\" to diffcore-break, use\n+                 60% for diffcore-merge-broken).\n+\t-B/60   (the same as above, since diffcore-break defautls to\n+\t\t 50%).\n+\n+\n+diffcore-pickaxe\n+----------------\n+\n+This transformation is used to find filepairs that represent\n+changes that touch a specified string, and is controlled by the\n+-S option and the --pickaxe-all option to the git-diff-*\n+commands.\n+\n+When diffcore-pickaxe is in use, it checks if there are\n+filepairs whose \"original\" side has the specified string and\n+whose \"result\" side does not.  Such a filepair represents \"the\n+string appeared in this changeset\".  It also checks for the\n+opposite case that loses the specified string.\n+\n+When --pickaxe-all is not in effect, diffcore-pickaxe leaves\n+only such filepairs that touches the specified string in its\n+output.  When --pickaxe-all is used, diffcore-pickaxe leaves all\n+filepairs intact if there is such a filepair, or makes the\n+output empty otherwise.  The latter behaviour is designed to\n+make reviewing of the changes in the context of the whole\n+changeset easier.\n+\n+\n+diffcore-order\n+--------------\n+\n+This is used to reorder the filepairs according to the user's\n+(or project's) taste, and is controlled by the -O option to the\n+git-diff-* commands.\n+\n+This takes a text file each of whose line is a shell glob\n+pattern.  Filepairs that match a glob pattern on an earlier line\n+in the file are output before ones that match a later line, and\n+filepairs that do not match any glob pattern are output last.\n+\n+As an example, typical orderfile for the core GIT probably\n+should look like this:\n+\n+    README\n+    Makefile\n+    Documentation\n+    *.h\n+    *.c\n+    t\n+\n------------\n\n"},{"id":"4625","messageId":"7v64wswbil.fsf@assigned-by-dhcp.cox.net","threadId":"841","inReplyTo":"7vr7fg1ofh.fsf@assigned-by-dhcp.cox.net","subject":"[PATCH] Documentation: describe diff tweaking (fix).","fromName":"Junio C Hamano","fromEmail":"junkio@cox.net","sentAt":"2005-06-06T00:54:10Z","receivedAt":"2005-06-06T00:54:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"I cannot count ;-)\n\nSigned-off-by: Junio C Hamano <junkio@cox.net>\n---\ndiff --git a/Documentation/diffcore.txt b/Documentation/diffcore.txt\n--- a/Documentation/diffcore.txt\n+++ b/Documentation/diffcore.txt\n@@ -45,7 +45,7 @@ the -p option is not used.  E.g.\n The diffcore mechanism is fed a list of such comparison results\n (each of which is called \"filepair\", although at this point each\n of them talks about a single file), and transforms such a list\n-into another list.  There are currently 7 such transformations:\n+into another list.  There are currently 6 such transformations:\n \n  - diffcore-pathspec\n  - diffcore-break\n\n\n\n"}]}