{"thread":{"id":"27965","subject":"File Systems and a Theory of Edits","startedAt":"2011-07-30T14:29:36Z","lastAt":"2011-08-01T12:01:18Z","messageCount":15,"participants":["Michael Nahas","Ævar Arnfjörð Bjarmason","John M. Dlugosz","René Scharfe","Michael Witten","Andreas Schwab","Junio C Hamano","Jeff King"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"172393","messageId":"CADo4Y9hG=-Bye5g7OWROJNbbUOcnH0hj0f3csws5V+YzEUKAMg@mail.gmail.com","threadId":"27965","inReplyTo":null,"subject":"File Systems and a Theory of Edits","fromName":"Michael Nahas","fromEmail":"mike.nahas@gmail.com","sentAt":"2011-07-30T14:29:36Z","receivedAt":"2011-07-30T14:29:36Z","isPatch":false,"sender":{"key":"mike.nahas@gmail.com","avatar":null},"body":"I've spent a month thinking about the design of git.  This is the\nresult of that work.\n\n\nMy understand of git is that, at the lower level, it stores and\ncommunicates snapshots of a file system.  At the upper level, git\nmanipulates \"edit\"s: the change between two snapshots.\n\nI'm proposing:\n    1) Creating git commands that mimic Unix's file system commands\n       and operate on those snapshots.\n    2) A language for describing git's manipulations of edits\n    3) Creating aliases that will allow the working tree and state\n       stored in the index to be treated like file systems\n\n\nI want to thank Jeff King (\"Peff\") for being my sounding board for the\ntheory of edits.\n\n1) Snapshots\n2) A Theory of Edits\n3) File Systems\n3.1) Merge Conflict\n4) Conclusion\n\n\n1) Snapshots\n\nCommits consist of:\n    1) A snapshot of the file system\n    2) Some meta-information\n    3) link(s) to past commit(s)\n\nI'm only concerned about #1 here.\n\nThe way to make something both easy to learn and easy to remember is\nto imitate something the user is already familiar with.  Thus my\nproposal is:\n\n\nPROPOSAL 1: git should imitate the Unix file system commands for\naccessing the snapshot of a commit.\n\nFor these commands to work, the git command will have to include an\nargument that specifies which commit it operates on.  So some basic\nones might be:\n    \"git ls <commit> -- <path>\"\n    \"git cat <commit> -- <path>\"\n(There exists \"git ls-files\", \"git ls-tree\", and \"git cat-file\" but\nthey are not quite the same.)\n    \"git find <commit> -- ...\"\n    \"git grep <commit> -- <path>\" (Exists)\nThe Unix command \"diff\" compares two files/directories.  So, the \"git\"\nversion requires two commits to be specified.\n    \"git diff <commit> <commit> -- <path>\"   (Exists)\nI'd love to see something to apply a command to every file in a commit\nor every file found by \"git find\".\n    \"git xargs <commit> ...\"  (Is this possible?)\nSince snapshots are a read-only version of a file system, git can't\nimplement the commands \"rm\", \"mv\", or \"cp\".\n\n\n2) A Theory of Edits\n\nSnapshots in the object store are easy to understand.  But to go\nfurther, we need to be able to look at the index file and the working\ntree.  During a merge conflict, the index file and working tree go\ninto an unusual state.  To understand that state, I spent a month\ncoming up with a mathematical theory to describe what git does.\n\nGit, at the upper level, manipulates edits.  An \"edit\" here is a very\nspecific term.  It is the changes between two specific snapshots.  I'm\ngoing to introduce some notation: if two snapshots are A and B, then\nthe edit is written A:B.\n\n==============\nWARNING: Great boredom ahead.  Mathematicians and theoriticians:\nenjoy!  Everyone else: read as much as you can and when you start to\nfall asleep, skip to the next subsection.\n==============\n\nEdits have mathematical properties.  It's easy to see that B:A is the\n\"inverse edit\" of A:B.  The edit A:A is the \"empty edit\" for snapshot\nA.  An edit A:B can be \"split\" using a snapshot C to make edits\nA:C and C:B or, written another way, A:C:B.  Likewise, edits A:B and\nB:C can be \"joined\" to form A:C.\n\n    * The inverse edit is generated by \"git revert\".\n    * The empty edit can be written by \"git commit --allow-empty\".\n    * Splitting an edit will be demonstrated later using \"git add\".\n    * Joining an edit is done \"git commit --amend\"\n\nAn edit has a specific start and end snapshot.  If you want to do a\nsimilar change with a different starting snapshot, you need to\n\"patch\"; patch() is a function that takes an edit and a new starting\nstate and returns the ending snapshot of a new edit.  So, patch(A:B,\nC) may return D, where C:D is a new edit containing a change similar\nto A:B.  I say \"may return\" because a patch starting at snapshot C\nmight not exist.  For example, if the edit A:B moves file \"foo.txt\" to\n\"bar.txt\" and snapshot C does not have a file \"foo.txt\" nor \"bar.txt\",\nthen the patch cannot exist.  [Note, there can be many definitions of\na patch() function. I'm not picking one; I'm just saying one exists.]\n\n    * patch() is most easily seen in \"git cherry-pick\"\n\nThe last definition concerns reordering edits A:B and B:C.  The edits\nare reorderable if a patch of B:C can put in front of a patch for A:B\nand the resulting edit still ends up at the same final snapshot\nC. Formally, A:B:C is \"reorderable\" if there exists A:D:C such that\npatch(B:C, A) = D and patch(A:B, D) = C.\n\n    \"git rebase --interactive\" can reorder (and do anything else!)\n\n\nPROPOSAL 2: adopt a term like edit and rigorous terms\nlike split, join, and reorder to describe the operations of git\ncommands.\nWe should also use exacting vocabulary to describe git commands.  It's\nnot unusual to use the word \"commit\" when referring to:\n    * a snapshot  (stored in the commit's tree object)\n    * an edit   (the difference between this commit's snapshot and its\n                   parent's (if it has only one parent...))\n    * a complete history of edits going back to the initial snapshot\n    * the commit object itself (e.g., when tagged)\nWhile often the appropriate definition can be picked up from context,\nwe should be precise if possible.\nIt would be good to define a term like \"snapshot tree\" that refers to\na tree object that is the root of a snapshot, to differentiate it from\nother tree objects that store subdirectories.\n\n\n3) File Systems : There exist snapshots outside the object store!\n\nThis statement may surprise you: The current state of the working tree\nis a snapshot.  The working tree is a file system so its state at any\none point, is a snapshot of a file system.  For brevity, I'm going to\ncall that snapshot WTREE.  We can talk about the edit between any\nother snapshot (like ones stored in a commit) and WTREE.  Usually,\nwe'll talk about the edit from HEAD to WTREE.\n\nIf the edit from HEAD to WTREE contains more than one feature and we\nwant to package each feature into its own edit, we need to split the\nHEAD to WTREE edit.  And, to split an edit, we need another\nsnapshot...\n\nAnother surprising statement: A snapshot can be computed from the\nindex file and HEAD (when not in merge-conflict state).  My validation\nfor this statement is that at any point, we can type \"commit\n--allow-empty\" and a new commit will be written to the current branch.\nThat commit contains a snapshot generated from the index file and\nHEAD.  Since the snapshot computed from the index file and HEAD will\nbecome the next commit written, I'll refer to it as NEXT.\n\nI want to be clear that NEXT is not the index file.  NEXT is a\nsnapshot.  The index file is a file.  The index file (with HEAD) is\njust one way to store a snapshot.  Since we can modify the files that\nwill go in the next commit, NEXT is actually a file system like WTREE.\nAlthough the man page for \"git add\" says it \"add[s] file contents to\nthe index\", I think a better way to say it is that it copies the files\ninto the NEXT file system.\n\nTo recap: a common operation in git is to split the HEAD to WTREE edit\nby \"git add\"ing files to the NEXT file system and then using \"git\ncommit\" to write a snapshot of NEXT into the object store, making the\nedit permanent.  (You may want to reread that sentence a few times\nuntil it becomes clear.)\n\nNow, the concepts of WTREE and NEXT work most of the time.  However,\nwhen there is a merge conflict, the index file takes on a special\nstate.  This is why I developed a theory around edits: I need it to\ndescribe what happens then and why.\n\n\n4) Merge Conflict\n\nI'm going to use \"git cherry-pick\" for my example.  It involves\nmerging a single edit, so it's the easiest case.\n\nA cherry-pick is almost a direct application of patch().  We have an\nedit A:B and we want to move it onto snapshot C.  But we said earlier,\nthe result of a patch() function may or may not exist.\n\nIf patch(A:B, C) exists and equals D, then git just writes the\nsnapshot D as the new commit.\n\nBut what if patch(A:B, C) does not exist?  Git does something amazing:\nit splits A:B!  So, we'll introduce a new state S to get A:S:B.  Now,\nthe first edit, A:S, contains all the parts of A:B that can be\npatch()ed onto state C, and the second edit, S:B, contains all the\nparts of A:B that cannot be patch()ed onto state C.  Obviously,\npatch(A:S, C) exists and the resulting snapshot is copied into NEXT.\n\nBut what happens to the unpatchable part in edit S:B?  We don't want\nthis change thrown away - it could be important.  We want it presented\nto the user and let the user fix or dismiss it.  If we had a GUI, the\nwindow's border might turn red and tabs for each affected file might\nopen, but a command-line interface doesn't have that.  So, git writes\nsomething reflecting the unpatachable part into files in the working\ntree and marks the files as \"needs review\" in the index file.  (It\nalso caches some files SHAs in the index, but we can ignore that.)\n\nNow that we know what happens during a conflicted merge, the question\nis: do there exist any snapshots here?  We defined NEXT using the\nsnapshot that would go in the next commit.  But if you run \"git commit\n--allow-empty\" during a merge conflict, you get an error!  We said the\ncurrent working tree state was a snapshot, but git just wrote\n\"<<<<\"\"====\"\">>>>\" into the files - if they did obey any syntax before\nthat, they certainly don't now!\n\nThe answer is unclear.  My opinion is that there's little harm in\nviewing the result of patch(A:S,C) as NEXT.  (This would be \"the\nsnapshot generated using stage 0 of the index file\" to some.)  I also\nthink that, during a merge conflict, the working tree is in an\nunsyntactic, unnatural state.  While I think there is value to always\ntreating the working tree as a file system, I can understand with\nthose who might argue that git should treat it differently during a\nmerge conflict.\n\n\nPROPOSAL 3: Add aliases NEXT and WTREE that work in place of a\nsnapshot in any commands.\n     e.g., \"git diff HEAD NEXT\"\n     e.g., \"git ls NEXT etc/\"\nDuring a conflicted merge state, we _may_ want commands to treat WTREE\ndifferently.\n\nADDITION TO PROPOSAL 2: Since NEXT and WTREE are writeable file\nsystems, the Unix filesystem commands that write should be implemented\nas part of git to work with them.\n    \"git cp <snapshot> <writeable_filesys> -- <src_path> <dest_file>\"\n    \"git mv <snapshot> <writeable_filesys> -- <src_path> <dest_file>\"\n    \"git rm <writeable_filesys> -- <file>\"\nI believe \"git cp\" would be similar to the proposed \"git put\".  The current\n\"git mv\" and \"git rm\" does operation on both NEXT and WTREE by default.\n(Which I think is a sensible default in those cases.)\nWe may want to consider \"mkdir\", \"rmdir\", \"chmod\".\n\n\n4) Conclusion\n\nI've proposed that git give snapshots the same interface that a Unix\ncommand line would provide to a read-only file system.\n\nI've presented a mathematical language for defining edits and\nproposed using it and clearer words for describing git command's\noperations.\n\nI've proposed creating the aliases WTREE and NEXT and allowing them to\nbe used anywhere a snapshot is used and in Unix commands that operate\non a writeable filesystem.\n\n\nMike Nahas\n\n\n\n\nAppendix: Features and Edits\n\nI said above \"If the edit from HEAD to WTREE contains more than one\nfeature and we want to package each feature into its own edit, ...\".\nI believe this concept of one-feature=one-edit is at the heart of good\ngit usage.  We want to manipulate features - add a feature to a\nbranch, remove a feature, etc. - but we can only manipulate edits.\nSo, as long as each feature is in its own edit, we can easily manipulate\nit.\n\nUnfortunately, features and edits are not the same.  We can merge two\nedits, but that doesn't mean the result has both features.  For\nexample, consider a project that branches and one branch's feature is\na new Makefile target and the edit explicitly lists the source files.\nThe other branch's feature is support for a new protocol and that edit\nadds a new source file.  The merge of these two branches may succeed\nand contain both edits, but it doesn't have both features.\n\nThe git glossary calls a merge \"evil\" if the commit contains a change\nthat is not present in either parent.  I say that's a bad\ndefinition.  In the example above, I think it's a good thing to edit\nthe merge so that the commit contains both features.\n\nThis is why I think this theory of edits has value: we want to\nmanipulate features and if we have one-feature=one-edit and we know\nhow to manipulate edits, then we can manipulate features.  I don't\nthink it is a new concept; I think it has been implied any number of\nplaces; I just hope with clear terms to describe manipulation of edits\nlike split/join/inverse/patch/reorder that we have clearer description\nof what we do.\n"},{"id":"172410","messageId":"CACBZZX48aDN_Njm+qMvovfz1tjdhnmXe5-bbJe=0_Q3LbLWoPA@mail.gmail.com","threadId":"27965","inReplyTo":"CADo4Y9hG=-Bye5g7OWROJNbbUOcnH0hj0f3csws5V+YzEUKAMg@mail.gmail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2011-07-30T19:06:33Z","receivedAt":"2011-07-30T19:06:33Z","isPatch":false,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Sat, Jul 30, 2011 at 16:29, Michael Nahas <mike.nahas@gmail.com> wrote:\n>     \"git xargs <commit> ...\"  (Is this possible?)\n\nI don't have comments on the rest of your proposal, but I've often\nwanted a git-find(1) similar to git-grep(1). Which would give you this\nfunctionality.\n\nThen you could simply:\n\n    git find <commit> <path> -type f | xargs <whatever>\n\nOr something like that.\n"},{"id":"172411","messageId":"23101-1312054868-691056@sneakemail.com","threadId":"27965","inReplyTo":"CADo4Y9hG=-Bye5g7OWROJNbbUOcnH0hj0f3csws5V+YzEUKAMg@mail.gmail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"John M. Dlugosz","fromEmail":"ngnr63q02@sneakemail.com","sentAt":"2011-07-30T19:40:57Z","receivedAt":"2011-07-30T19:40:57Z","isPatch":false,"sender":{"key":"ngnr63q02@sneakemail.com","avatar":null},"body":"On 7/30/2011 9:29 AM, Michael Nahas wrote:\n> For these commands to work, the git command will have to include an\n> argument that specifies which commit it operates on.  So some basic\n> ones might be:\n>      \"git ls<commit>  -- <path>\"\n>      \"git cat<commit>  -- <path>\"\n> (There exists \"git ls-files\", \"git ls-tree\", and \"git cat-file\" but\n\nIf you could \"mount\" a repository, then you would not need these commands at all.  It \nwould be in fact a read-only file system.  Once mounted, the individual commits could be \ndirectories, and under that you explore in the usual way.\n"},{"id":"172424","messageId":"4E350F15.9050009@lsrfire.ath.cx","threadId":"27965","inReplyTo":"CACBZZX48aDN_Njm+qMvovfz1tjdhnmXe5-bbJe=0_Q3LbLWoPA@mail.gmail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2011-07-31T08:15:17Z","receivedAt":"2011-07-31T08:15:17Z","isPatch":false,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 30.07.2011 21:06, schrieb Ævar Arnfjörð Bjarmason:\n> On Sat, Jul 30, 2011 at 16:29, Michael Nahas <mike.nahas@gmail.com> wrote:\n>>     \"git xargs <commit> ...\"  (Is this possible?)\n> \n> I don't have comments on the rest of your proposal, but I've often\n> wanted a git-find(1) similar to git-grep(1). Which would give you this\n> functionality.\n> \n> Then you could simply:\n> \n>     git find <commit> <path> -type f | xargs <whatever>\n> \n> Or something like that.\n\nHow about this, which should match your example:\n\n\tgit ls-tree -r --name-only <commit> <path> | xargs <whatever>\n\nRené\n"},{"id":"172439","messageId":"8f33c6bd053f4f89a2766c542773c38c-mfwitten@gmail.com","threadId":"27965","inReplyTo":"23101-1312054868-691056@sneakemail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"Michael Witten","fromEmail":"mfwitten@gmail.com","sentAt":null,"receivedAt":"2011-07-31T12:08:39Z","isPatch":false,"sender":{"key":"mfwitten@gmail.com","avatar":"https://avatars.githubusercontent.com/u/597101?v=4"},"body":"On Sat, 30 Jul 2011 14:40:57 -0500, John M. Dlugosz wrote:\n\n> On 7/30/2011 9:29 AM, Michael Nahas wrote:\n> \n>> For these commands to work, the git command will have to include an\n>> argument that specifies which commit it operates on.  So some basic\n>> ones might be:\n>>      \"git ls<commit>  -- <path>\"\n>>      \"git cat<commit>  -- <path>\"\n>> (There exists \"git ls-files\", \"git ls-tree\", and \"git cat-file\" but\n> \n> If you could \"mount\" a repository, then you would not need these commands at all.  It \n> would be in fact a read-only file system.  Once mounted, the individual commits could be \n> directories, and under that you explore in the usual way.\n\nYou can do this kind of thing with Avery Pennarun's\nmost awesome `bup' tool, which is based on git, and\nit is indeed very useful.\n\nSee the whole thread here:\n\n Subject: Request: Auto-joining large files by 'bup fuse'\n Message-ID: <5f12a43ec3dc4250a7672725f5c172fc-mfwitten@gmail.com>\n http://groups.google.com/group/bup-list/browse_thread/thread/f80f56981853698b\n"},{"id":"172453","messageId":"CADo4Y9gECLJ45g_r-uZBRnfEVXBRw2EoF2HkRu=0-eJ2YCuBLA@mail.gmail.com","threadId":"27965","inReplyTo":"CADo4Y9gU_Z73gCPCESvVZhLOJUJg+mTqHkeqpNv2L8xLJvKxEQ@mail.gmail.com","subject":"RE: File Systems and a Theory of Edits","fromName":"Michael Nahas","fromEmail":"mike.nahas@gmail.com","sentAt":"2011-07-31T14:15:01Z","receivedAt":"2011-07-31T14:15:01Z","isPatch":false,"sender":{"key":"mike.nahas@gmail.com","avatar":null},"body":"Rene,\nI don't doubt that there exists current commands in git that can\nperform operations like cat, ls, etc.  My point is that git can make\nit easier for new users to learn commands and existing users to\nremember commands if git copies the name and sematics (as much as\npossible) of cat, ls, etc.\n\nÆvar,\nThe issue is what goes inside the xargs command.  If it is unix's cat\ncommand, the files listed by find will be from the commit's snapshot,\nbut the files read by cat will be from the working tree.\n\nI believe the solution for xargs may be John D.'s solution - to\n\"mount\" the snapshot as a file system.  And the \"mount\" command in git\nis \"git checkout\".  (Now, I almost want to rename \"git checkout\" to\n\"git remount\"!)\n\n\nMike Nahas\n\n\nOn Sun, Jul 31, 2011 at 4:15 AM, René Scharfe\n<rene.scharfe@lsrfire.ath.cx> wrote:\n>\n> Am 30.07.2011 21:06, schrieb Ævar Arnfjörð Bjarmason:\n> > On Sat, Jul 30, 2011 at 16:29, Michael Nahas <mike.nahas@gmail.com> wrote:\n> >>     \"git xargs <commit> ...\"  (Is this possible?)\n> >\n> > I don't have comments on the rest of your proposal, but I've often\n> > wanted a git-find(1) similar to git-grep(1). Which would give you this\n> > functionality.\n> >\n> > Then you could simply:\n> >\n> >     git find <commit> <path> -type f | xargs <whatever>\n> >\n> > Or something like that.\n>\n> How about this, which should match your example:\n>\n>        git ls-tree -r --name-only <commit> <path> | xargs <whatever>\n>\n> René\n"},{"id":"172457","messageId":"4E357FE3.1040205@lsrfire.ath.cx","threadId":"27965","inReplyTo":"CADo4Y9gU_Z73gCPCESvVZhLOJUJg+mTqHkeqpNv2L8xLJvKxEQ@mail.gmail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"René Scharfe","fromEmail":"rene.scharfe@lsrfire.ath.cx","sentAt":"2011-07-31T16:16:35Z","receivedAt":"2011-07-31T16:16:35Z","isPatch":false,"sender":{"key":"l.s.r@web.de","avatar":"https://avatars.githubusercontent.com/u/26122331?v=4"},"body":"Am 31.07.2011 16:13, schrieb Michael Nahas:\n> I don't doubt that there exists current commands in git that can perform\n> operations like cat, ls, etc.  My point is that git can make it easier\n> for new users to learn commands and existing users to remember commands\n> if git copies the name and sematics (as much as possible) of cat, ls, etc.\n\nPossibly.  My point was that for this example a look-alike was easy to\nimplement as an alias or shell script using an existing plumbing\ncommand.  You can probably get quite far to your goal that way.\n\nRené\n"},{"id":"172458","messageId":"CAMOZ1BtrgO1XhJfR2-1Mpd8Ytrz4pjVyhbPdbNxDP84hhiip+A@mail.gmail.com","threadId":"27965","inReplyTo":"CADo4Y9gECLJ45g_r-uZBRnfEVXBRw2EoF2HkRu=0-eJ2YCuBLA@mail.gmail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"Michael Witten","fromEmail":"mfwitten@gmail.com","sentAt":"2011-07-31T17:21:27Z","receivedAt":"2011-07-31T17:21:27Z","isPatch":false,"sender":{"key":"mfwitten@gmail.com","avatar":"https://avatars.githubusercontent.com/u/597101?v=4"},"body":"On Sun, Jul 31, 2011 at 14:15, Michael Nahas <mike.nahas@gmail.com> wrote:\n> I believe the solution for xargs may be John D.'s solution - to\n> \"mount\" the snapshot as a file system.  And the \"mount\" command in git\n> is \"git checkout\".  (Now, I almost want to rename \"git checkout\" to\n> \"git remount\"!)\n\nWhy not just `git mount', though? We could have different mount points\ntoo, so that it's easy to work with multiple `snapshots' at once (in\nthe spirit of bazaar and mercurial, as well).\n\nPerhaps `git umount' could be used to make the repository bare.\n\nIn any case, I always find myself wishing that the standard interfaces\nwould make it easier to base an operation on a snapshot that is not\nyet mounted as the working tree. It can be quite cumbersome to switch\nthe contents of the working tree.\n"},{"id":"172470","messageId":"CADo4Y9i=PYBv33Jnu2osQX_FL97ng9FZ8TFeMMuc5CDGUhu1Gg@mail.gmail.com","threadId":"27965","inReplyTo":"CAMOZ1BtrgO1XhJfR2-1Mpd8Ytrz4pjVyhbPdbNxDP84hhiip+A@mail.gmail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"Michael Nahas","fromEmail":"mike.nahas@gmail.com","sentAt":"2011-07-31T21:13:11Z","receivedAt":"2011-07-31T21:13:11Z","isPatch":false,"sender":{"key":"mike.nahas@gmail.com","avatar":null},"body":"Why not \"git mount\" indeed!\n\nAt work, I have 3 very active branches and a slow build system.  Right\nnow, when I switch to a new branch, I have to rebuild everything.\nBeing able to \"git mount\" 3 snapshots in 3 directories with three\ndifferent build outputs would make switching branches faster.\n\n3 working trees would be even better.  I've been wondering if I can\nmake another working trees by creating a .git/ directory and\nsymlinking to the .git/objects and ./git/refs of my current\nrepository.  (I could use the environment variables GIT_INDEX_FILE and\nGIT_WORKING_TREE, but that would require setting and resetting them.\nOr using a different shell.)\n\nSo a true \"git mount\" that allowed mounting editable branches would be\nvery useful to me.  (Although, if it wasn't for that crappy build\nsystem, I prefer a single working tree.)\n\nMike Nahas\n\n\nOn Sun, Jul 31, 2011 at 1:21 PM, Michael Witten <mfwitten@gmail.com> wrote:\n> On Sun, Jul 31, 2011 at 14:15, Michael Nahas <mike.nahas@gmail.com> wrote:\n>> I believe the solution for xargs may be John D.'s solution - to\n>> \"mount\" the snapshot as a file system.  And the \"mount\" command in git\n>> is \"git checkout\".  (Now, I almost want to rename \"git checkout\" to\n>> \"git remount\"!)\n>\n> Why not just `git mount', though? We could have different mount points\n> too, so that it's easy to work with multiple `snapshots' at once (in\n> the spirit of bazaar and mercurial, as well).\n>\n> Perhaps `git umount' could be used to make the repository bare.\n>\n> In any case, I always find myself wishing that the standard interfaces\n> would make it easier to base an operation on a snapshot that is not\n> yet mounted as the working tree. It can be quite cumbersome to switch\n> the contents of the working tree.\n>\n"},{"id":"172474","messageId":"m2sjpmt7lq.fsf@igel.home","threadId":"27965","inReplyTo":"CADo4Y9i=PYBv33Jnu2osQX_FL97ng9FZ8TFeMMuc5CDGUhu1Gg@mail.gmail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"Andreas Schwab","fromEmail":"schwab@linux-m68k.org","sentAt":"2011-07-31T22:20:49Z","receivedAt":"2011-07-31T22:20:49Z","isPatch":false,"sender":{"key":"schwab@linux-m68k.org","avatar":"https://avatars.githubusercontent.com/u/2175493?v=4"},"body":"Michael Nahas <mike.nahas@gmail.com> writes:\n\n> 3 working trees would be even better.  I've been wondering if I can\n> make another working trees by creating a .git/ directory and\n> symlinking to the .git/objects and ./git/refs of my current\n> repository.\n\nHave you looked at git-new-workdir?\n\nAndreas.\n\n-- \nAndreas Schwab, schwab@linux-m68k.org\nGPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5\n\"And now for something completely different.\"\n"},{"id":"172475","messageId":"CADo4Y9gYCfWD3hfc8h0_Q_VCof4+=G-oX4HZyK+LFy3kRVZk+A@mail.gmail.com","threadId":"27965","inReplyTo":"m2sjpmt7lq.fsf@igel.home","subject":"Re: File Systems and a Theory of Edits","fromName":"Michael Nahas","fromEmail":"mike.nahas@gmail.com","sentAt":"2011-07-31T22:39:37Z","receivedAt":"2011-07-31T22:39:37Z","isPatch":false,"sender":{"key":"mike.nahas@gmail.com","avatar":null},"body":"I shall check it out.  Thanks!  -Mike\n\nOn Sun, Jul 31, 2011 at 6:20 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:\n> Michael Nahas <mike.nahas@gmail.com> writes:\n>\n>> 3 working trees would be even better.  I've been wondering if I can\n>> make another working trees by creating a .git/ directory and\n>> symlinking to the .git/objects and ./git/refs of my current\n>> repository.\n>\n> Have you looked at git-new-workdir?\n>\n> Andreas.\n>\n> --\n> Andreas Schwab, schwab@linux-m68k.org\n> GPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5\n> \"And now for something completely different.\"\n>\n"},{"id":"172481","messageId":"7vy5zej611.fsf@alter.siamese.dyndns.org","threadId":"27965","inReplyTo":"4E350F15.9050009@lsrfire.ath.cx","subject":"Re: File Systems and a Theory of Edits","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-08-01T01:04:58Z","receivedAt":"2011-08-01T01:04:58Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"René Scharfe <rene.scharfe@lsrfire.ath.cx> writes:\n\n> Am 30.07.2011 21:06, schrieb Ævar Arnfjörð Bjarmason:\n>> On Sat, Jul 30, 2011 at 16:29, Michael Nahas <mike.nahas@gmail.com> wrote:\n>>>     \"git xargs <commit> ...\"  (Is this possible?)\n>> \n>> I don't have comments on the rest of your proposal, but I've often\n>> wanted a git-find(1) similar to git-grep(1). Which would give you this\n>> functionality.\n>> \n>> Then you could simply:\n>> \n>>     git find <commit> <path> -type f | xargs <whatever>\n>> \n>> Or something like that.\n>\n> How about this, which should match your example:\n>\n> \tgit ls-tree -r --name-only <commit> <path> | xargs <whatever>\n\nI don't get what this thread wants to achieve quite yet.\n\nThe devil is in <whatever> part. What would it do, given only the sequence\nof pathnames and object names but not data?  Invoke low-level git commands\non them?\n"},{"id":"172484","messageId":"20110801012237.GA32509@sigill.intra.peff.net","threadId":"27965","inReplyTo":"23101-1312054868-691056@sneakemail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-08-01T01:22:38Z","receivedAt":"2011-08-01T01:22:38Z","isPatch":false,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sat, Jul 30, 2011 at 02:40:57PM -0500, John M. Dlugosz wrote:\n\n> On 7/30/2011 9:29 AM, Michael Nahas wrote:\n> >For these commands to work, the git command will have to include an\n> >argument that specifies which commit it operates on.  So some basic\n> >ones might be:\n> >     \"git ls<commit>  -- <path>\"\n> >     \"git cat<commit>  -- <path>\"\n> >(There exists \"git ls-files\", \"git ls-tree\", and \"git cat-file\" but\n> \n> If you could \"mount\" a repository, then you would not need these\n> commands at all.  It would be in fact a read-only file system.  Once\n> mounted, the individual commits could be directories, and under that\n> you explore in the usual way.\n\nThere are several (mostly fuse-based) tools listed on the wiki:\n\n  https://git.wiki.kernel.org/index.php/InterfacesFrontendsAndTools#Filesystem_interfaces\n\nI've never used any of them, though. No idea how mature or usable they\nare.\n\nGoogling around also came up with this newer attempt:\n\n  https://github.com/mfontani/git-fuse-perl\n\nAgain, no idea on the quality.\n\n-Peff\n"},{"id":"172519","messageId":"CADo4Y9g8pA7ew6LrcHWpBo0ym5R8aTmtkfXGsUm3Ytx5-rfXxQ@mail.gmail.com","threadId":"27965","inReplyTo":"7vy5zej611.fsf@alter.siamese.dyndns.org","subject":"Re: File Systems and a Theory of Edits","fromName":"Michael Nahas","fromEmail":"mike.nahas@gmail.com","sentAt":"2011-08-01T11:14:15Z","receivedAt":"2011-08-01T11:14:15Z","isPatch":false,"sender":{"key":"mike.nahas@gmail.com","avatar":null},"body":"Hi Junio,\n\nI started this thread with a very long post that rejoins the NEXT /\nWTREE debate with more ammunition.  (A theory to back it up and\nexplain what happens during merge conflict.)\n\nI also proposed that git treat snapshots, the working tree, and next\ncommit like unix file systems and support the commands from them such\nas: cat, ls, find, etc.  These follow-up emails were focused on the\nsmall problem of whether or not xargs could work.  (I'm now convince\nit can't - you want to just to a checkout and then run it.)\n\nI excepted the proposals below.\n\nMike\n\n\n\nPROPOSAL 3: Add aliases NEXT and WTREE that work in place of a\nsnapshot in any commands.\n     e.g., \"git diff HEAD NEXT\"\n     e.g., \"git ls NEXT etc/\"\nDuring a conflicted merge state, we _may_ want commands to treat WTREE\ndifferently.\n\n\nPROPOSAL 1: git should imitate the Unix file system commands for\naccessing the snapshot of a commit.\n\nFor these commands to work, the git command will have to include an\nargument that specifies which commit it operates on.  So some basic\nones might be:\n    \"git ls <commit> -- <path>\"\n    \"git cat <commit> -- <path>\"\n(There exists \"git ls-files\", \"git ls-tree\", and \"git cat-file\" but\nthey are not quite the same.)\n    \"git find <commit> -- ...\"\n    \"git grep <commit> -- <path>\" (Exists)\nThe Unix command \"diff\" compares two files/directories.  So, the \"git\"\nversion requires two commits to be specified.\n    \"git diff <commit> <commit> -- <path>\"   (Exists)\nI'd love to see something to apply a command to every file in a commit\nor every file found by \"git find\".\n    \"git xargs <commit> ...\"  (Is this possible?)\nSince snapshots are a read-only version of a file system, git can't\nimplement the commands \"rm\", \"mv\", or \"cp\" for them.\nNEXT and WTREE are writeable file\nsystems, the Unix filesystem commands that write should be implemented\nas part of git to work with them.\n    \"git cp <snapshot> <writeable_filesys> -- <src_path> <dest_file>\"\n    \"git mv <snapshot> <writeable_filesys> -- <src_path> <dest_file>\"\n    \"git rm <writeable_filesys> -- <file>\"\nI believe \"git cp\" would be similar to the proposed \"git put\".  The current\n\"git mv\" and \"git rm\" does operation on both NEXT and WTREE by default.\n(Which I think is a sensible default in those cases.)\nWe may want to consider \"mkdir\", \"rmdir\", \"chmod\".\n\n\nPROPOSAL 2: adopt a term like edit and rigorous terms\nlike split, join, and reorder to describe the operations of git\ncommands.\nWe should also use exacting vocabulary to describe git commands.  It's\nnot unusual to use the word \"commit\" when referring to:\n    * a snapshot  (stored in the commit's tree object)\n    * an edit   (the difference between this commit's snapshot and its\n                   parent's (if it has only one parent...))\n    * a complete history of edits going back to the initial snapshot\n    * the commit object itself (e.g., when tagged)\nWhile often the appropriate definition can be picked up from context,\nwe should be precise if possible.\nIt would be good to define a term like \"snapshot tree\" that refers to\na tree object that is the root of a snapshot, to differentiate it from\nother tree objects that store subdirectories.\n"},{"id":"172532","messageId":"CADo4Y9gtsKS660GCXObMeKztED+EJLBtHDHregvbMyR3S2_gUQ@mail.gmail.com","threadId":"27965","inReplyTo":"CADo4Y9i=PYBv33Jnu2osQX_FL97ng9FZ8TFeMMuc5CDGUhu1Gg@mail.gmail.com","subject":"Re: File Systems and a Theory of Edits","fromName":"Michael Nahas","fromEmail":"mike.nahas@gmail.com","sentAt":"2011-08-01T12:01:18Z","receivedAt":"2011-08-01T12:01:18Z","isPatch":false,"sender":{"key":"mike.nahas@gmail.com","avatar":null},"body":"Michael,\n\nI've been thinking about it and \"git mount\" is the right idea.  I like\nit a lot.  In fact, the most common usage of \"git checkout\" can be\ntotally replaced by \"git mount\".\n\nThe other usage of \"git checkout -- file\" can be replaced by \"git cp\".\n\nMike\n\n\nOn Sun, Jul 31, 2011 at 5:13 PM, Michael Nahas <mike.nahas@gmail.com> wrote:\n> Why not \"git mount\" indeed!\n>\n> At work, I have 3 very active branches and a slow build system.  Right\n> now, when I switch to a new branch, I have to rebuild everything.\n> Being able to \"git mount\" 3 snapshots in 3 directories with three\n> different build outputs would make switching branches faster.\n>\n> 3 working trees would be even better.  I've been wondering if I can\n> make another working trees by creating a .git/ directory and\n> symlinking to the .git/objects and ./git/refs of my current\n> repository.  (I could use the environment variables GIT_INDEX_FILE and\n> GIT_WORKING_TREE, but that would require setting and resetting them.\n> Or using a different shell.)\n>\n> So a true \"git mount\" that allowed mounting editable branches would be\n> very useful to me.  (Although, if it wasn't for that crappy build\n> system, I prefer a single working tree.)\n>\n> Mike Nahas\n>\n>\n> On Sun, Jul 31, 2011 at 1:21 PM, Michael Witten <mfwitten@gmail.com> wrote:\n>> On Sun, Jul 31, 2011 at 14:15, Michael Nahas <mike.nahas@gmail.com> wrote:\n>>> I believe the solution for xargs may be John D.'s solution - to\n>>> \"mount\" the snapshot as a file system.  And the \"mount\" command in git\n>>> is \"git checkout\".  (Now, I almost want to rename \"git checkout\" to\n>>> \"git remount\"!)\n>>\n>> Why not just `git mount', though? We could have different mount points\n>> too, so that it's easy to work with multiple `snapshots' at once (in\n>> the spirit of bazaar and mercurial, as well).\n>>\n>> Perhaps `git umount' could be used to make the repository bare.\n>>\n>> In any case, I always find myself wishing that the standard interfaces\n>> would make it easier to base an operation on a snapshot that is not\n>> yet mounted as the working tree. It can be quite cumbersome to switch\n>> the contents of the working tree.\n>>\n>\n"}]}