{"thread":{"id":"27570","subject":"[RFC/PATCH] git put: an alternative to add/reset/checkout","startedAt":"2011-06-07T20:06:59Z","lastAt":"2012-01-23T18:10:57Z","messageCount":18,"participants":["Jeff King","Junio C Hamano","Michael Nahas","Nguyen Thai Ngoc Duy","Jakub Narebski","Matthieu Moy"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"169501","messageId":"20110607200659.GA6177@sigill.intra.peff.net","threadId":"27570","inReplyTo":null,"subject":"[RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-06-07T20:06:59Z","receivedAt":"2011-06-07T20:06:59Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"This is an idea I've had for a while, but I was inspired to push it\nforward a bit by Mike's command-line thread.\n\nOne problem I have seen people complain about is how \"reset\" and\n\"checkout\" are somewhat overloaded to pull content into and out of the\nindex (since they also do things like moving HEAD or switching\nbranches). Those commands took the approach of saying \"reset is about\nchanging the HEAD and possibly the index; therefore \"reset -- file\"\nshould be about pulling things from a commit into the index\". And that\nis certainly one way to think about it.\n\nBut another way to think about it is that commits, the index, and the\nworking tree are all \"locations\" with content. And one common operation\nyou may want to do is to move content from one spot to another, either\nwhole, by file, or by diff hunks. To a new user, knowing that \"add\" is\nthe command for moving content from thet working tree to the index does\nnot help them know which command to use to do the opposite content\nmovement.\n\nSo the \"reset -- <file>\" command is easily discoverable if you come at\nit one way (I already know what reset does, but I want to reset just\nsome specific file), but not another way (I know how to move content one\nway, but not the other way).\n\nMy idea is therefore to have a single command for moving content from\none location to another. You specify a source and a destination and get\na uniform interface for moving content.\n\nA proof-of-concept patch is below. Be aware that is meant to be\nillustrative and is not well tested. Also, it is a minimal presentation\nof the concept. Other \"locations\" may also be meaningful. I'll include\nsome ideas below the patch.\n\n---\n Makefile   |    1 +\n git-put.sh |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n 2 files changed, 71 insertions(+), 0 deletions(-)\n create mode 100644 git-put.sh\n\ndiff --git a/Makefile b/Makefile\nindex e40ac0c..4564506 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -368,6 +368,7 @@ SCRIPT_SH += git-merge-one-file.sh\n SCRIPT_SH += git-merge-resolve.sh\n SCRIPT_SH += git-mergetool.sh\n SCRIPT_SH += git-pull.sh\n+SCRIPT_SH += git-put.sh\n SCRIPT_SH += git-quiltimport.sh\n SCRIPT_SH += git-rebase.sh\n SCRIPT_SH += git-repack.sh\ndiff --git a/git-put.sh b/git-put.sh\nnew file mode 100644\nindex 0000000..f673e14\n--- /dev/null\n+++ b/git-put.sh\n@@ -0,0 +1,70 @@\n+#!/bin/sh\n+\n+SUBDIRECTORY_OK=Yes\n+OPTIONS_KEEPDASHASH=Yes\n+OPTIONS_SPEC=\"\\\n+git put [options] <from> <to> [--] <file...>\n+\n+Move contents from one place to another, where <from> and <to> are one of:\n+  1. A commit (e.g., master, HEAD~10, v1.7.5)\n+  2. The special token INDEX to indicate git's index.\n+  3. The special token WORKTREE to indicate the working directory.\n+\n+Options:\n+--\n+p            don't move whole files; use the patch interface\n+\"\n+. git-sh-setup\n+\n+patch=\n+while test $# != 0; do\n+\tcase \"$1\" in\n+\t-p) patch=--patch ;;\n+\t--) shift; break ;;\n+\t*) usage ;;\n+\tesac\n+\tshift\n+done\n+test $# -lt 2 && usage\n+\n+from=$1; shift\n+to=$1; shift\n+test \"$1\" = \"--\" && shift\n+\n+type_of() {\n+\tcase \"$1\" in\n+\tINDEX) echo index ;;\n+\tWORKTREE) echo worktree ;;\n+\t*) echo commit ;;\n+\tesac\n+}\n+\n+# Checkout contents to worktree without munging the index in\n+# between.\n+worktree_checkout() {\n+\told=$GIT_INDEX_FILE\n+\ttest -z \"$old\" && old=$(git rev-parse --git-dir)/index\n+\tnew=$(git rev-parse --git-dir)/put-index.tmp\n+\tcp \"$old\" \"$new\" &&\n+\tGIT_INDEX_FILE=$new git checkout \"$@\"\n+\tstatus=$?\n+\trm -f \"$new\"\n+\texit $status\n+}\n+\n+case \"$(type_of \"$from\"),$(type_of \"$to\")\" in\n+*,commit)\n+\tdie \"You can't modify an existing commit.\" ;;\n+index,index)\n+\tdie \"You can't move content from the index on top of itself.\" ;;\n+worktree,index)\n+\texec git add $patch -- \"$@\" ;;\n+commit,index)\n+\texec git reset $patch \"$from\" -- \"$@\" ;;\n+index,worktree)\n+\texec git checkout $patch -- \"$@\" ;;\n+worktree,worktree)\n+\tdie \"You can't move content in the worktree on top of itself.\" ;;\n+commit,worktree)\n+\tworktree_checkout $patch \"$from\" -- \"$@\" ;;\n+esac\n\n\nAs you can see, this handles only three typoes of locations: the\nworktree, the index, and an arbitrary commit (really a tree-ish). Some\nother types I've thought of are:\n\n  - stashes; you can already use stashes a source with \"stash@{0}\". They\n    could also be a destination, chaining to \"git stash\".\n\n  - branches as destinations; obviously we can't change an existing\n    commit, but what about something like:\n\n      git put WORKTREE BRANCH:foo\n\n    to optionally create a new branch \"refs/heads/foo\" based on the\n    current HEAD, push changes into a temporary index that matches its\n    tip, and then making a new commit based on top.\n\n    This would serve a similar purpose to stashes, except that they\n    would be named and could operate as full branches. I would find it\n    useful for picking apart a mass of worktree changes into discrete\n    commits.\n\n  - allow multiple destinations, like\n\n     # equivalent to \"git checkout --\"\n     git put HEAD INDEX,WORKTREE\n\n  - blobs as locations. We could allow something like:\n\n      git put v1.7.5:Makefile WORKTREE:Makefile\n\n    which would be equivalent to\n\n      git put v1.7.5 WORKTREE -- Makefile\n\n    but sometimes matches the user's mental model better. It also allows\n    pulling blobs from index stages, like:\n\n      # Resolve in favor of \"ours\"\n      git put :2:Makefile INDEX,WORKTREE\n\n  - subtrees as locations. This allows a form of renaming between old\n    versions.\n\n      git put gitgui-0.10.0: WORKTREE:git-gui\n\n\nI hope it's obvious from what I wrote above and from the implementation,\nbut this would not be _replacing_ other commands, but would just be\nanother way of looking at them. By having more than one way to do the\nsame thing, it helps people discover the way that fits their mental\nmodel most appropriately.  Of course, it may also just introduce insane\nconfusion.\n\nLet the flaming begin.\n\n-Peff\n"},{"id":"169508","messageId":"7vvcwh4ako.fsf@alter.siamese.dyndns.org","threadId":"27570","inReplyTo":"20110607200659.GA6177@sigill.intra.peff.net","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2011-06-07T21:04:55Z","receivedAt":"2011-06-07T21:04:55Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> As you can see, this handles only three typoes of locations: the\n\nIs that a recursive typo, or a typo of type?\n\n> worktree, the index, and an arbitrary commit (really a tree-ish).\n\n> Some other types I've thought of are:\n>\n>   - stashes; you can already use stashes a source with \"stash@{0}\". They\n>     could also be a destination, chaining to \"git stash\".\n\nNo opinion on this.\n\n>   - branches as destinations; obviously we can't change an existing\n>     commit, but what about something like:\n>\n>       git put WORKTREE BRANCH:foo\n>\n>     to optionally create a new branch \"refs/heads/foo\" based on the\n>     current HEAD, push changes into a temporary index that matches its\n>     tip, and then making a new commit based on top.\n>\n>     This would serve a similar purpose to stashes, except that they\n>     would be named and could operate as full branches. I would find it\n>     useful for picking apart a mass of worktree changes into discrete\n>     commits.\n\nShould \"git put WORKTREE HEAD\" be equivalent to \"git commit -A\" then?\n\n>   - allow multiple destinations, like\n>\n>      # equivalent to \"git checkout --\"\n>      git put HEAD INDEX,WORKTREE\n\nThis is close to going overboard, but OK.\n\n>   - blobs as locations. We could allow something like:\n>\n>       git put v1.7.5:Makefile WORKTREE:Makefile\n>\n>     which would be equivalent to\n>\n>       git put v1.7.5 WORKTREE -- Makefile\n>\n>     but sometimes matches the user's mental model better. It also allows\n>     pulling blobs from index stages, like:\n>\n>       # Resolve in favor of \"ours\"\n>       git put :2:Makefile INDEX,WORKTREE\n\nMore importantly, it would allow people to do things like...\n\n\tgit put v1.7.5:Makefile WORKTREE:oMakefile\n        magicdiff oMakefile Makefile\n\n>   - subtrees as locations. This allows a form of renaming between old\n>     versions.\n>\n>       git put gitgui-0.10.0: WORKTREE:git-gui\n\nThis is a natural extension of the above \"we could rename\" theme, right?\n\n> ...  Of course, it may also just introduce insane\n> confusion.\n\nThe only worry about confusion is if people incorrectly think these magic\ntokens are not mere syntax sugars available only in \"put\", especially,\nthey look so similar to \"HEAD\" which is _not_ syntax sugar and can be used\nelsewhere. Other than that, I think this is a nice approach.\n"},{"id":"169509","messageId":"20110607214532.GB7663@sigill.intra.peff.net","threadId":"27570","inReplyTo":"7vvcwh4ako.fsf@alter.siamese.dyndns.org","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-06-07T21:45:32Z","receivedAt":"2011-06-07T21:45:32Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Tue, Jun 07, 2011 at 02:04:55PM -0700, Junio C Hamano wrote:\n\n> > As you can see, this handles only three typoes of locations: the\n> Is that a recursive typo, or a typo of type?\n\nIt's art; the viewer is free to interpret based on their own\nexperiences.\n\n> > Some other types I've thought of are:\n> >\n> >   - stashes; you can already use stashes a source with \"stash@{0}\". They\n> >     could also be a destination, chaining to \"git stash\".\n> \n> No opinion on this.\n\nMy initial prototype was going to have stash as a fourth location. But I\nbacked out a little because it was complex, and the more I think about\nit, I'm not sure it's really appropriate. You can already pull _from_ a\nstash by naming its commit. And putting into a stash is a bit different\nthan a put, because it handles both the index and the worktree, and\nremoves the changes from them afterwards.\n\nSo I think a better match is the idea of \"git put\" to a new commit on a\nnamed branch that I showed elsewhere. And then you can \"git put\" off of\nit later.\n\n> >   - branches as destinations; obviously we can't change an existing\n> >     commit, but what about something like:\n> >\n> >       git put WORKTREE BRANCH:foo\n> >\n> >     to optionally create a new branch \"refs/heads/foo\" based on the\n> >     current HEAD, push changes into a temporary index that matches its\n> >     tip, and then making a new commit based on top.\n> \n> Should \"git put WORKTREE HEAD\" be equivalent to \"git commit -A\" then?\n\nI'm tempted to say yes, with two reservations:\n\n  1. Making a new commit (or even a new branch) somehow seems more\n     heavyweight to me than just picking changes. So I'm reluctant to do\n     it for just \"git put $from HEAD\"; maybe there should be a special\n     token that says \"yeah, make a new commit\". Like:\n\n       git put WORKTREE COMMIT:HEAD\n\n     to commit on top of HEAD, or even\n\n       git put WORKTREE AMEND:HEAD\n\n     to amend HEAD (this would be useful when building up a commit\n     piece by piece using \"git put\").\n\n     But that is getting very magical. I have a vague feeling you could\n     actually reimplement a lot of the user-facing portions of git in\n     terms of these \"put\" operations. For example, forget the index as a\n     whole and have \"NEXT\", \"BASE\", \"OURS\", and \"THEIRS\" representing\n     trees of the various stages.\n\n     I'm not sure if that's just insane, though. That _isn't_ how the\n     index actually works (e.g., resolved paths would have only a NEXT\n     entry, so the other trees would actually be partial trees). So\n     we're making an abstraction over it, and when that abstraction\n     leaks, I fear things will get very confusing for the user.\n\n  2. There is a slight incompatibility between the \"git put\" mental\n     model and what really happens. I already ran into it once with \"git\n     put HEAD WORKTREE\", and it appears here again. The issue is that\n     you generally _don't_ put items straight from a commit to the\n     worktree and vice versa. They go through the index.\n\n     So I took care with \"git put HEAD WORKTREE\" that the index was not\n     touched. That makes the command very obvious and keeps the sources\n     and destinations as orthogonal as possible. But is it really what\n     the user wants? In the case of \"checkout\", I'm not sure. In the\n     case of \"commit -A\", you probably _do_ want to update the index if\n     the commit is HEAD, and _don't_ if it is another branch.\n\n     But now we're getting magical again. So the question becomes:\n     should git put just be a pure _wrapper_ around these other\n     commands to aid in discoverability, and do sensible things for each\n     combination, or should it be a purely orthogonal \"pick content from\n     source to destination\" command?\n\n> >   - allow multiple destinations, like\n> >\n> >      # equivalent to \"git checkout --\"\n> >      git put HEAD INDEX,WORKTREE\n> \n> This is close to going overboard, but OK.\n\nYeah, I'm still kind of brainstorming, but I think you might be right.\nBut see above for why \"git put\" should possibly just be doing it for\nyou automatically.\n\n> >   - subtrees as locations. This allows a form of renaming between old\n> >     versions.\n> >\n> >       git put gitgui-0.10.0: WORKTREE:git-gui\n> \n> This is a natural extension of the above \"we could rename\" theme, right?\n\nYeah, I think so.\n\n> The only worry about confusion is if people incorrectly think these magic\n> tokens are not mere syntax sugars available only in \"put\", especially,\n> they look so similar to \"HEAD\" which is _not_ syntax sugar and can be used\n> elsewhere. Other than that, I think this is a nice approach.\n\nI think it might be worth using the same tokens in \"diff\", but yeah,\nthey definitely should not go elsewhere.\n\nI find the all-caps ugly, and it is part of what confuses them with\nHEAD. At the same time, we are using the same namespace that ref lookup\nuses. So calling it \"worktree\" might be too ambiguous. I tried to avoid\nusing \"--worktree\" because I wanted to make it clear that these were\nordered arguments, not options.\n\nThere's also one other complication with the whole idea, which is that\nthere are two separate things you might want to move: content itself, or\n_changes_ in content.\n\nThat is, think about the way stashes work. We don't apply the difference\nbetween the stashed content and our working tree. We look at the\ndifference between the stashed content and its parent, and then apply\nthose changes to the working tree.\n\nWhen I do \"checkout -p $commit $file\", I am often not interested in\nseeing all of the differences between where I am now and where $commit\nis, but rather in seeing the differences introduced by $commit, and\npulling them selectively into my current version of $file. Sort of a\n\"cherry-pick -p\".\n\nShould \"put\" support that kind of usage? What would it look like?\n\n  git put commit:v1.7.5 WORKTREE Makefile\n\n? Or even:\n\n  git put v1.7.4..v1.7.5 WORKTREE Makefile\n\nI dunno. Maybe this whole thing is too crazy. I'll think on it some\nmore, and maybe some other people will comment.\n\n-Peff\n"},{"id":"169532","messageId":"BANLkTinT41oU=CVnGkmkeXk5u5=KnWjmDA@mail.gmail.com","threadId":"27570","inReplyTo":"20110607214532.GB7663@sigill.intra.peff.net","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Michael Nahas","fromEmail":"mike.nahas@gmail.com","sentAt":"2011-06-08T03:07:16Z","receivedAt":"2011-06-08T03:07:16Z","isPatch":true,"sender":{"key":"mike.nahas@gmail.com","avatar":null},"body":"Junio wrote:\n>The only worry about confusion is if people incorrectly think these magic\n>tokens are not mere syntax sugars available only in \"put\", especially,\n>they look so similar to \"HEAD\" which is _not_ syntax sugar and can be used\n>elsewhere. Other than that, I think this is a nice approach.\n\nI don't think they are syntactic sugar.\n\nThe working tree is a tree.  HEAD is a tree.  HEAD is also a commit\nand a file in .git/, so it is more than a tree, but it's a tree.  NEXT\nis a tree.   There may be different code to read (or write) each of\nthem, but they are all trees.  So I don't see these labels as\nsyntactic sugar -- making a commonly used piece of code easier to use\n(like ++) -- but as presenting a common interface to a concept that\nmay have different implementations.\n\nI think this \"git put\" command let's people think in terms of trees.\nCommits are read-only trees.  NEXT and WTREE are tree that can be\nwritten to.  It's up for debate if stashes are read-only or writeable.\n\nTo me \"git put\" is just the UNIX \"cp\" command, just that files or\ndirectories can be prefixed by tree names.  In fact, I'd make sure the\n\"-r\" option was used when copying whole trees or subtrees. :)\n\ngit put -r HEAD WTREE\ngit put HEAD:foo.txt WTREE:foo.txt\n\nI would keep it like \"cp\" and drop the support for copying to multiple\ntrees (like HEAD and INDEX) in a single command.  I would have a good\nform for copying multiple files from one tree to another.  E.g., \"git\nput HEAD:{foo.txt,bar.txt} WTREE\" or \"git put HEAD WTREE foo.txt\nbar.txt\" or \"git put HEAD:*.txt WTREE\" even.\n\nI do not think \"COMMIT\" or \"AMEND\" should be part of the command.\n\n\"git put\" could replace \"git add\", \"git checkout -- <file>\", and \"git\nreset -- <file>\".  It would not replace the other common file\nmanipulators: \"git rm\" and \"git mv\".\n\nDamn, I'm tempted to say screw \"git put\" and call it \"git cp\".  Then\nchange \"git rm\" and \"git mv\" to support writeable trees and you've got\nyourself a very easy to learn interface!\n\n\nJeff wrote:\n> The issue is that\n> you generally _don't_ put items straight from a commit to the\n> worktree and vice versa. They go through the index.\n\nGoing through the index is only the right move if you're going backwards.\n\nHEAD is the most recent commit.  NEXT should be what you already know\nwill go in the next commit.  WTREE is stuff that may go into NEXT or\ninto another future commit or may never go in at all.   So, HEAD and\nall previous commits are the past; NEXT is the near future; and WTREE\nis the far future.\n\nIf you are reverting a mistake, you are copying from HEAD or some\nother ancestor to NEXT and WTREE.  Especially if you're copying from\nHEAD, you want to include the target NEXT, since you know that that\ncode will almost assuredly work and be part of the next commit.  In\nfact, the opposite of \"git add\" (the awkward \"git checkout -- <file>\")\nis to copy a file from HEAD to NEXT --- essentially pushing off the\nchange from NEXT to some future commit.\n\nIn every other case, you want new stuff to go into WTREE and skip the\nNEXT.  The way I view merge is that the new files are copied from\nanother branch into WTREE.  All resolved changes are then moved into\nNEXT.  If there are no unresolved changed, a new commit is made.\nWhile this may not be the actual sequence of events that Git performs,\nit's how I see the operation - new changes are introduced at WTREE,\ncorrect changes are moved into NEXT, and the commit operation makes\nthem permanent.\n\n\n\n\n\nOn Tue, Jun 7, 2011 at 5:45 PM, Jeff King <peff@peff.net> wrote:\n> On Tue, Jun 07, 2011 at 02:04:55PM -0700, Junio C Hamano wrote:\n>\n>> > As you can see, this handles only three typoes of locations: the\n>> Is that a recursive typo, or a typo of type?\n>\n> It's art; the viewer is free to interpret based on their own\n> experiences.\n>\n>> > Some other types I've thought of are:\n>> >\n>> >   - stashes; you can already use stashes a source with \"stash@{0}\". They\n>> >     could also be a destination, chaining to \"git stash\".\n>>\n>> No opinion on this.\n>\n> My initial prototype was going to have stash as a fourth location. But I\n> backed out a little because it was complex, and the more I think about\n> it, I'm not sure it's really appropriate. You can already pull _from_ a\n> stash by naming its commit. And putting into a stash is a bit different\n> than a put, because it handles both the index and the worktree, and\n> removes the changes from them afterwards.\n>\n> So I think a better match is the idea of \"git put\" to a new commit on a\n> named branch that I showed elsewhere. And then you can \"git put\" off of\n> it later.\n>\n>> >   - branches as destinations; obviously we can't change an existing\n>> >     commit, but what about something like:\n>> >\n>> >       git put WORKTREE BRANCH:foo\n>> >\n>> >     to optionally create a new branch \"refs/heads/foo\" based on the\n>> >     current HEAD, push changes into a temporary index that matches its\n>> >     tip, and then making a new commit based on top.\n>>\n>> Should \"git put WORKTREE HEAD\" be equivalent to \"git commit -A\" then?\n>\n> I'm tempted to say yes, with two reservations:\n>\n>  1. Making a new commit (or even a new branch) somehow seems more\n>     heavyweight to me than just picking changes. So I'm reluctant to do\n>     it for just \"git put $from HEAD\"; maybe there should be a special\n>     token that says \"yeah, make a new commit\". Like:\n>\n>       git put WORKTREE COMMIT:HEAD\n>\n>     to commit on top of HEAD, or even\n>\n>       git put WORKTREE AMEND:HEAD\n>\n>     to amend HEAD (this would be useful when building up a commit\n>     piece by piece using \"git put\").\n>\n>     But that is getting very magical. I have a vague feeling you could\n>     actually reimplement a lot of the user-facing portions of git in\n>     terms of these \"put\" operations. For example, forget the index as a\n>     whole and have \"NEXT\", \"BASE\", \"OURS\", and \"THEIRS\" representing\n>     trees of the various stages.\n>\n>     I'm not sure if that's just insane, though. That _isn't_ how the\n>     index actually works (e.g., resolved paths would have only a NEXT\n>     entry, so the other trees would actually be partial trees). So\n>     we're making an abstraction over it, and when that abstraction\n>     leaks, I fear things will get very confusing for the user.\n>\n>  2. There is a slight incompatibility between the \"git put\" mental\n>     model and what really happens. I already ran into it once with \"git\n>     put HEAD WORKTREE\", and it appears here again. The issue is that\n>     you generally _don't_ put items straight from a commit to the\n>     worktree and vice versa. They go through the index.\n>\n>     So I took care with \"git put HEAD WORKTREE\" that the index was not\n>     touched. That makes the command very obvious and keeps the sources\n>     and destinations as orthogonal as possible. But is it really what\n>     the user wants? In the case of \"checkout\", I'm not sure. In the\n>     case of \"commit -A\", you probably _do_ want to update the index if\n>     the commit is HEAD, and _don't_ if it is another branch.\n>\n>     But now we're getting magical again. So the question becomes:\n>     should git put just be a pure _wrapper_ around these other\n>     commands to aid in discoverability, and do sensible things for each\n>     combination, or should it be a purely orthogonal \"pick content from\n>     source to destination\" command?\n>\n>> >   - allow multiple destinations, like\n>> >\n>> >      # equivalent to \"git checkout --\"\n>> >      git put HEAD INDEX,WORKTREE\n>>\n>> This is close to going overboard, but OK.\n>\n> Yeah, I'm still kind of brainstorming, but I think you might be right.\n> But see above for why \"git put\" should possibly just be doing it for\n> you automatically.\n>\n>> >   - subtrees as locations. This allows a form of renaming between old\n>> >     versions.\n>> >\n>> >       git put gitgui-0.10.0: WORKTREE:git-gui\n>>\n>> This is a natural extension of the above \"we could rename\" theme, right?\n>\n> Yeah, I think so.\n>\n>> The only worry about confusion is if people incorrectly think these magic\n>> tokens are not mere syntax sugars available only in \"put\", especially,\n>> they look so similar to \"HEAD\" which is _not_ syntax sugar and can be used\n>> elsewhere. Other than that, I think this is a nice approach.\n>\n> I think it might be worth using the same tokens in \"diff\", but yeah,\n> they definitely should not go elsewhere.\n>\n> I find the all-caps ugly, and it is part of what confuses them with\n> HEAD. At the same time, we are using the same namespace that ref lookup\n> uses. So calling it \"worktree\" might be too ambiguous. I tried to avoid\n> using \"--worktree\" because I wanted to make it clear that these were\n> ordered arguments, not options.\n>\n> There's also one other complication with the whole idea, which is that\n> there are two separate things you might want to move: content itself, or\n> _changes_ in content.\n>\n> That is, think about the way stashes work. We don't apply the difference\n> between the stashed content and our working tree. We look at the\n> difference between the stashed content and its parent, and then apply\n> those changes to the working tree.\n>\n> When I do \"checkout -p $commit $file\", I am often not interested in\n> seeing all of the differences between where I am now and where $commit\n> is, but rather in seeing the differences introduced by $commit, and\n> pulling them selectively into my current version of $file. Sort of a\n> \"cherry-pick -p\".\n>\n> Should \"put\" support that kind of usage? What would it look like?\n>\n>  git put commit:v1.7.5 WORKTREE Makefile\n>\n> ? Or even:\n>\n>  git put v1.7.4..v1.7.5 WORKTREE Makefile\n>\n> I dunno. Maybe this whole thing is too crazy. I'll think on it some\n> more, and maybe some other people will comment.\n>\n> -Peff\n>\n"},{"id":"169619","messageId":"BANLkTink9T7M5989Ntpnt5jYcn3bdCXKhQ@mail.gmail.com","threadId":"27570","inReplyTo":"20110607200659.GA6177@sigill.intra.peff.net","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-06-08T15:18:38Z","receivedAt":"2011-06-08T15:18:38Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Wed, Jun 8, 2011 at 3:06 AM, Jeff King <peff@peff.net> wrote:\n> But another way to think about it is that commits, the index, and the\n> working tree are all \"locations\" with content. And one common operation\n> you may want to do is to move content from one spot to another, either\n> whole, by file, or by diff hunks.\n\nAlso \"git put --pretend\" or \"git put --dry-run\" may show the diff of\ncontent movement, without actual moving. \"--dry-run --patch\"\ncombination probably does not make sense though.\n\n> As you can see, this handles only three typoes of locations: the\n> worktree, the index, and an arbitrary commit (really a tree-ish). Some\n> other types I've thought of are:\n>\n>  ....\n>\n\nI find it intuitive (given a source tree and destination one(s), you\ncan copy content by paths or even by hunks), until you give it more\npowers (creating new branch or commit, move subdirs...). The original\ngit-put idea could reduce a lot of confusion for new users. Your extra\ntypes seem uncommon to me (or can be well covered with current\ncommands without much confusion). For advanced use cases, maybe the\ncurrent command set can be enhanced with new options.\n-- \nDuy\n"},{"id":"169645","messageId":"m3hb80dynr.fsf@localhost.localdomain","threadId":"27570","inReplyTo":"20110607214532.GB7663@sigill.intra.peff.net","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-06-08T17:25:27Z","receivedAt":"2011-06-08T17:25:27Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Jeff King <peff@peff.net> writes:\n\n> I find the all-caps ugly, and it is part of what confuses them with\n> HEAD. At the same time, we are using the same namespace that ref lookup\n> uses. So calling it \"worktree\" might be too ambiguous. I tried to avoid\n> using \"--worktree\" because I wanted to make it clear that these were\n> ordered arguments, not options.\n\nPerhaps we can use some character that is forbidden in ref names,\ndoesn't make trouble when doing allowed operations on said refs, won't\nconfuse user, and is not trouble with shell... ehhh...\n\n* @{wtree} would confuse users that it has something to do with reflog\n* [tree]   would be trouble with some shells\n* ~tree~   looks a bit strange, might be trouble with username expansion  \n* :tree:   might be mistaken for 'tree:' in index\n\n-- \nJakub Narebski\nPoland\nShadeHawk on #git\n"},{"id":"169646","messageId":"vpqtyc0nsfw.fsf@bauges.imag.fr","threadId":"27570","inReplyTo":"m3hb80dynr.fsf@localhost.localdomain","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-06-08T17:28:35Z","receivedAt":"2011-06-08T17:28:35Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Jeff King <peff@peff.net> writes:\n>\n>> I find the all-caps ugly, and it is part of what confuses them with\n>> HEAD. At the same time, we are using the same namespace that ref lookup\n>> uses. So calling it \"worktree\" might be too ambiguous. I tried to avoid\n>> using \"--worktree\" because I wanted to make it clear that these were\n>> ordered arguments, not options.\n>\n> Perhaps we can use some character that is forbidden in ref names,\n> doesn't make trouble when doing allowed operations on said refs, won't\n> confuse user, and is not trouble with shell... ehhh...\n>\n> * @{wtree} would confuse users that it has something to do with reflog\n\nWell, we already have @{upstream} ...\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"169647","messageId":"20110608173012.GA4279@sigill.intra.peff.net","threadId":"27570","inReplyTo":"vpqtyc0nsfw.fsf@bauges.imag.fr","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2011-06-08T17:30:12Z","receivedAt":"2011-06-08T17:30:12Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Wed, Jun 08, 2011 at 07:28:35PM +0200, Matthieu Moy wrote:\n\n> > Jeff King <peff@peff.net> writes:\n> >\n> >> I find the all-caps ugly, and it is part of what confuses them with\n> >> HEAD. At the same time, we are using the same namespace that ref lookup\n> >> uses. So calling it \"worktree\" might be too ambiguous. I tried to avoid\n> >> using \"--worktree\" because I wanted to make it clear that these were\n> >> ordered arguments, not options.\n> >\n> > Perhaps we can use some character that is forbidden in ref names,\n> > doesn't make trouble when doing allowed operations on said refs, won't\n> > confuse user, and is not trouble with shell... ehhh...\n> >\n> > * @{wtree} would confuse users that it has something to do with reflog\n> \n> Well, we already have @{upstream} ...\n\nYes, but like all of the @{} things, it's a modifier for the left-hand\nside. So \"master@{upstream}\" is meaningful, and \"@{upstream}\" is the\nsame as \"HEAD@{upstream}\".\n\nWhat does \"master@{wtree}\" mean?\n\n-Peff\n"},{"id":"169650","messageId":"vpqlixcns6m.fsf@bauges.imag.fr","threadId":"27570","inReplyTo":"20110608173012.GA4279@sigill.intra.peff.net","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-06-08T17:34:09Z","receivedAt":"2011-06-08T17:34:09Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jeff King <peff@peff.net> writes:\n\n> On Wed, Jun 08, 2011 at 07:28:35PM +0200, Matthieu Moy wrote:\n>\n>> > Jeff King <peff@peff.net> writes:\n>> >\n>> > * @{wtree} would confuse users that it has something to do with reflog\n>> \n>> Well, we already have @{upstream} ...\n>\n> Yes, but like all of the @{} things, it's a modifier for the left-hand\n> side. So \"master@{upstream}\" is meaningful, and \"@{upstream}\" is the\n> same as \"HEAD@{upstream}\".\n>\n> What does \"master@{wtree}\" mean?\n\nNothing, but then we already have @{-1} ;-).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"169651","messageId":"201106081950.04910.jnareb@gmail.com","threadId":"27570","inReplyTo":"vpqlixcns6m.fsf@bauges.imag.fr","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-06-08T17:50:03Z","receivedAt":"2011-06-08T17:50:03Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Matthieu Moy wrote:\n> Jeff King <peff@peff.net> writes:\n> > On Wed, Jun 08, 2011 at 07:28:35PM +0200, Matthieu Moy wrote:\n> >> > Jeff King <peff@peff.net> writes:\n> >> >\n> >> > * @{wtree} would confuse users that it has something to do with reflog\n> >> \n> >> Well, we already have @{upstream} ...\n> >\n> > Yes, but like all of the @{} things, it's a modifier for the left-hand\n> > side. So \"master@{upstream}\" is meaningful, and \"@{upstream}\" is the\n> > same as \"HEAD@{upstream}\".\n> >\n> > What does \"master@{wtree}\" mean?\n> \n> Nothing, but then we already have @{-1} ;-).\n\nThat's actually HEAD reflog.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"169654","messageId":"vpq62ogkxs0.fsf@bauges.imag.fr","threadId":"27570","inReplyTo":"201106081950.04910.jnareb@gmail.com","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2011-06-08T18:01:35Z","receivedAt":"2011-06-08T18:01:35Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Jakub Narebski <jnareb@gmail.com> writes:\n\n> Matthieu Moy wrote:\n>> Jeff King <peff@peff.net> writes:\n>> > On Wed, Jun 08, 2011 at 07:28:35PM +0200, Matthieu Moy wrote:\n>> >> > Jeff King <peff@peff.net> writes:\n>> >> >\n>> >> > * @{wtree} would confuse users that it has something to do with reflog\n>> >> \n>> >> Well, we already have @{upstream} ...\n>> >\n>> > Yes, but like all of the @{} things, it's a modifier for the left-hand\n>> > side. So \"master@{upstream}\" is meaningful, and \"@{upstream}\" is the\n>> > same as \"HEAD@{upstream}\".\n>> >\n>> > What does \"master@{wtree}\" mean?\n>> \n>> Nothing, but then we already have @{-1} ;-).\n>\n> That's actually HEAD reflog.\n\nYes, but neither HEAD@{-1} nor master@{-1} work. So we have one instance\nof @{...} which is unrelated from reflog, and another which isn't a\nsuffix. @{wtree} would be both.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"169682","messageId":"201106082057.48139.jnareb@gmail.com","threadId":"27570","inReplyTo":"vpq62ogkxs0.fsf@bauges.imag.fr","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2011-06-08T18:57:47Z","receivedAt":"2011-06-08T18:57:47Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Matthieu Moy wrote:\n> Jakub Narebski <jnareb@gmail.com> writes:\n> > Matthieu Moy wrote:\n> >> Jeff King <peff@peff.net> writes:\n> >> > On Wed, Jun 08, 2011 at 07:28:35PM +0200, Matthieu Moy wrote:\n> >> >> > Jeff King <peff@peff.net> writes:\n> >> >> >\n> >> >> > * @{wtree} would confuse users that it has something to do with reflog\n> >> >> \n> >> >> Well, we already have @{upstream} ...\n> >> >\n> >> > Yes, but like all of the @{} things, it's a modifier for the left-hand\n> >> > side. So \"master@{upstream}\" is meaningful, and \"@{upstream}\" is the\n> >> > same as \"HEAD@{upstream}\".\n> >> >\n> >> > What does \"master@{wtree}\" mean?\n> >> \n> >> Nothing, but then we already have @{-1} ;-).\n> >\n> > That's actually HEAD reflog.\n> \n> Yes, but neither HEAD@{-1} nor master@{-1} work. So we have one instance\n> of @{...} which is unrelated from reflog, and another which isn't a\n> suffix. @{wtree} would be both.\n\nBut both are about refs (upstream of a ref, or previously checked-out ref).\n@{wtree} ain't.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"169843","messageId":"BANLkTimtBrvOFT41mZz_g8QgcBC=2KvNtQ@mail.gmail.com","threadId":"27570","inReplyTo":"m3hb80dynr.fsf@localhost.localdomain","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2011-06-10T12:38:52Z","receivedAt":"2011-06-10T12:38:52Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Thu, Jun 9, 2011 at 12:25 AM, Jakub Narebski <jnareb@gmail.com> wrote:\n> Perhaps we can use some character that is forbidden in ref names,\n> doesn't make trouble when doing allowed operations on said refs, won't\n> confuse user, and is not trouble with shell... ehhh...\n>\n> * :tree:   might be mistaken for 'tree:' in index\n\nAlso may clash (or make it more ambiguous) with pathspec magic. Another option\n\n* +tree\n-- \nDuy\n"},{"id":"182958","messageId":"CACsJy8BCGi3s8gXr4kk-u8tDWztV6ozg1Tap23Q=TxA5d9iL+g@mail.gmail.com","threadId":"27570","inReplyTo":"20110607200659.GA6177@sigill.intra.peff.net","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2012-01-23T10:32:31Z","receivedAt":"2012-01-23T10:32:31Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"(Bringing up an old thread)\n\nOn Wed, Jun 8, 2011 at 3:06 AM, Jeff King <peff@peff.net> wrote:\n> ...\n> But another way to think about it is that commits, the index, and the\n> working tree are all \"locations\" with content. And one common operation\n> you may want to do is to move content from one spot to another, either\n> whole, by file, or by diff hunks. To a new user, knowing that \"add\" is\n> the command for moving content from thet working tree to the index does\n> not help them know which command to use to do the opposite content\n> movement.\n> ...\n> My idea is therefore to have a single command for moving content from\n> one location to another. You specify a source and a destination and get\n> a uniform interface for moving content.\n>\n> A proof-of-concept patch is below. Be aware that is meant to be\n> illustrative and is not well tested. Also, it is a minimal presentation\n> of the concept. Other \"locations\" may also be meaningful. I'll include\n> some ideas below the patch.\n>\n> ---\n>  Makefile   |    1 +\n>  git-put.sh |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n>  2 files changed, 71 insertions(+), 0 deletions(-)\n>  create mode 100644 git-put.sh\n>\n> diff --git a/Makefile b/Makefile\n> index e40ac0c..4564506 100644\n> --- a/Makefile\n> +++ b/Makefile\n> @@ -368,6 +368,7 @@ SCRIPT_SH += git-merge-one-file.sh\n>  SCRIPT_SH += git-merge-resolve.sh\n>  SCRIPT_SH += git-mergetool.sh\n>  SCRIPT_SH += git-pull.sh\n> +SCRIPT_SH += git-put.sh\n>  SCRIPT_SH += git-quiltimport.sh\n>  SCRIPT_SH += git-rebase.sh\n>  SCRIPT_SH += git-repack.sh\n> diff --git a/git-put.sh b/git-put.sh\n> new file mode 100644\n> index 0000000..f673e14\n> --- /dev/null\n> +++ b/git-put.sh\n> @@ -0,0 +1,70 @@\n> +#!/bin/sh\n> +\n> +SUBDIRECTORY_OK=Yes\n> +OPTIONS_KEEPDASHASH=Yes\n> +OPTIONS_SPEC=\"\\\n> +git put [options] <from> <to> [--] <file...>\n> +\n> +Move contents from one place to another, where <from> and <to> are one of:\n> +  1. A commit (e.g., master, HEAD~10, v1.7.5)\n> +  2. The special token INDEX to indicate git's index.\n> +  3. The special token WORKTREE to indicate the working directory.\n> +\n> +Options:\n> +--\n> +p            don't move whole files; use the patch interface\n> +\"\n> +. git-sh-setup\n> +\n> +patch=\n> +while test $# != 0; do\n> +       case \"$1\" in\n> +       -p) patch=--patch ;;\n> +       --) shift; break ;;\n> +       *) usage ;;\n> +       esac\n> +       shift\n> +done\n> +test $# -lt 2 && usage\n> +\n> +from=$1; shift\n> +to=$1; shift\n> +test \"$1\" = \"--\" && shift\n> +\n> +type_of() {\n> +       case \"$1\" in\n> +       INDEX) echo index ;;\n> +       WORKTREE) echo worktree ;;\n> +       *) echo commit ;;\n> +       esac\n> +}\n> +\n> +# Checkout contents to worktree without munging the index in\n> +# between.\n> +worktree_checkout() {\n> +       old=$GIT_INDEX_FILE\n> +       test -z \"$old\" && old=$(git rev-parse --git-dir)/index\n> +       new=$(git rev-parse --git-dir)/put-index.tmp\n> +       cp \"$old\" \"$new\" &&\n> +       GIT_INDEX_FILE=$new git checkout \"$@\"\n> +       status=$?\n> +       rm -f \"$new\"\n> +       exit $status\n> +}\n> +\n> +case \"$(type_of \"$from\"),$(type_of \"$to\")\" in\n> +*,commit)\n> +       die \"You can't modify an existing commit.\" ;;\n> +index,index)\n> +       die \"You can't move content from the index on top of itself.\" ;;\n> +worktree,index)\n> +       exec git add $patch -- \"$@\" ;;\n> +commit,index)\n> +       exec git reset $patch \"$from\" -- \"$@\" ;;\n> +index,worktree)\n> +       exec git checkout $patch -- \"$@\" ;;\n> +worktree,worktree)\n> +       die \"You can't move content in the worktree on top of itself.\" ;;\n> +commit,worktree)\n> +       worktree_checkout $patch \"$from\" -- \"$@\" ;;\n> +esac\n>\n>\n> As you can see, this handles only three typoes of locations: the\n> worktree, the index, and an arbitrary commit (really a tree-ish).\n\nLast time we were stuck at the magic keywords INDEX and WORKTREE. What\nif we sort of follow scp naming convention:\n\n - Normal paths are working tree's paths\n - Paths with a colon in it are in \"remote\" locations (index or a\ntree). The part before colon specifies the location.\n\nWe could have:\n\ngit put <src> [<src>...] <dst>\ngit put <src> [<src>...] <dst> -- <pathspec>\n\nWhere <src> and <dst> could be\n\n - <tree-ish> <colon> [<pathspec>]\n - [0-3] <colon> [<pathspec>]\n - <pathspec> (or plain path)\n\nIn the first form, pathspec could be specified in <src>. If <dst> is\nworktree, then \".\" would be enough (or path to repo's root to be more\nstrict). In the second form, no pathspec can be part of <src> nor\n<dst> because they're at the end already.\n\nWith this syntax we could have:\n\ngit put 0:path/to/file.c . (or git put 0: path/to/file.c)\n -> copy file.c from index to worktree (at the same path \"path/to/file.c\")\ngit put path/to/file 0:\n -> copy file to index\ngit put HEAD: . -- path/\n -> checkout everything in path/ from HEAD\n\nI'm not sure how mutiple <src> should work, but there may be a use case for it.\n\n> Some other types I've thought of are:\n> ...\n>  - branches as destinations; obviously we can't change an existing\n>    commit, but what about something like:\n>\n>      git put WORKTREE BRANCH:foo\n>\n>    to optionally create a new branch \"refs/heads/foo\" based on the\n>    current HEAD, push changes into a temporary index that matches its\n>    tip, and then making a new commit based on top.\n>\n>    This would serve a similar purpose to stashes, except that they\n>    would be named and could operate as full branches. I would find it\n>    useful for picking apart a mass of worktree changes into discrete\n>    commits.\n>\n>  - allow multiple destinations, like\n>\n>     # equivalent to \"git checkout --\"\n>     git put HEAD INDEX,WORKTREE\n\nThese obviously do not work with the syntax I propose.\n-- \nDuy\n"},{"id":"182962","messageId":"CADo4Y9iH+J-X-TdqTN2Y9KhQnprnCVvC4Xy6qhVHwsBRmsZUrg@mail.gmail.com","threadId":"27570","inReplyTo":"CACsJy8BCGi3s8gXr4kk-u8tDWztV6ozg1Tap23Q=TxA5d9iL+g@mail.gmail.com","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Michael Nahas","fromEmail":"mike.nahas@gmail.com","sentAt":"2012-01-23T13:53:23Z","receivedAt":"2012-01-23T13:53:23Z","isPatch":true,"sender":{"key":"mike.nahas@gmail.com","avatar":null},"body":"On Mon, Jan 23, 2012 at 5:32 AM, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:\n>\n> (Bringing up an old thread)\n\n\"...thank you so much for bringing up such a painful subject. While\nyou're at it, why don't you give me a nice paper cut and pour lemon\njuice on it.\"\n\n\n\"git put\" is \"git cp\".  It copies from one filesystem (or a snapshot\nof a filesystem) to another filesystem.\n\nWithout multiple working directories, a modifiable \"stash\", or a\n(useful) name for the filesystem referred to as\n\"index\"/\"cache\"/\"staging area\", there is only one filesystem that the\ncommand can write to: the (singular) working directory.\n\nSo, \"git put <src filesystem> -- <path>\" is fine.  It will copy from\nthe path in the src filesystem to the path in the current working\ndirectory.  I don't think the command \"put\" is a great name for that.\nSince we already have some strange double-usage commands like \"git\ncheckout --\" and \"git reset --\", perhaps this should be \"git\ncherry-pick --\".\n\n<rant>\nBut for my money, \"git cp\" is clearer and I'd love to get rid of the\nuser-confusing double-usage commands.  I'd replace \"git checkout --\"\nwith \"git cp NEXT WTREE -- <path>\" and replace \"git reset --\" with\n\"git cp HEAD NEXT --\" where NEXT is the filesystem represented by the\n\"index\"/\"cache\"/\"staging area\" and WTREE is an alias for the working\ndirectory.\n</rant>\n\nStill, good luck.  It's a useful addition even if it is \"git cherry-pick --\".\n\nMike\n\n>\n>\n> On Wed, Jun 8, 2011 at 3:06 AM, Jeff King <peff@peff.net> wrote:\n> > ...\n> > But another way to think about it is that commits, the index, and the\n> > working tree are all \"locations\" with content. And one common operation\n> > you may want to do is to move content from one spot to another, either\n> > whole, by file, or by diff hunks. To a new user, knowing that \"add\" is\n> > the command for moving content from thet working tree to the index does\n> > not help them know which command to use to do the opposite content\n> > movement.\n> > ...\n> > My idea is therefore to have a single command for moving content from\n> > one location to another. You specify a source and a destination and get\n> > a uniform interface for moving content.\n> >\n> > A proof-of-concept patch is below. Be aware that is meant to be\n> > illustrative and is not well tested. Also, it is a minimal presentation\n> > of the concept. Other \"locations\" may also be meaningful. I'll include\n> > some ideas below the patch.\n> >\n> > ---\n> >  Makefile   |    1 +\n> >  git-put.sh |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\n> >  2 files changed, 71 insertions(+), 0 deletions(-)\n> >  create mode 100644 git-put.sh\n> >\n> > diff --git a/Makefile b/Makefile\n> > index e40ac0c..4564506 100644\n> > --- a/Makefile\n> > +++ b/Makefile\n> > @@ -368,6 +368,7 @@ SCRIPT_SH += git-merge-one-file.sh\n> >  SCRIPT_SH += git-merge-resolve.sh\n> >  SCRIPT_SH += git-mergetool.sh\n> >  SCRIPT_SH += git-pull.sh\n> > +SCRIPT_SH += git-put.sh\n> >  SCRIPT_SH += git-quiltimport.sh\n> >  SCRIPT_SH += git-rebase.sh\n> >  SCRIPT_SH += git-repack.sh\n> > diff --git a/git-put.sh b/git-put.sh\n> > new file mode 100644\n> > index 0000000..f673e14\n> > --- /dev/null\n> > +++ b/git-put.sh\n> > @@ -0,0 +1,70 @@\n> > +#!/bin/sh\n> > +\n> > +SUBDIRECTORY_OK=Yes\n> > +OPTIONS_KEEPDASHASH=Yes\n> > +OPTIONS_SPEC=\"\\\n> > +git put [options] <from> <to> [--] <file...>\n> > +\n> > +Move contents from one place to another, where <from> and <to> are one of:\n> > +  1. A commit (e.g., master, HEAD~10, v1.7.5)\n> > +  2. The special token INDEX to indicate git's index.\n> > +  3. The special token WORKTREE to indicate the working directory.\n> > +\n> > +Options:\n> > +--\n> > +p            don't move whole files; use the patch interface\n> > +\"\n> > +. git-sh-setup\n> > +\n> > +patch=\n> > +while test $# != 0; do\n> > +       case \"$1\" in\n> > +       -p) patch=--patch ;;\n> > +       --) shift; break ;;\n> > +       *) usage ;;\n> > +       esac\n> > +       shift\n> > +done\n> > +test $# -lt 2 && usage\n> > +\n> > +from=$1; shift\n> > +to=$1; shift\n> > +test \"$1\" = \"--\" && shift\n> > +\n> > +type_of() {\n> > +       case \"$1\" in\n> > +       INDEX) echo index ;;\n> > +       WORKTREE) echo worktree ;;\n> > +       *) echo commit ;;\n> > +       esac\n> > +}\n> > +\n> > +# Checkout contents to worktree without munging the index in\n> > +# between.\n> > +worktree_checkout() {\n> > +       old=$GIT_INDEX_FILE\n> > +       test -z \"$old\" && old=$(git rev-parse --git-dir)/index\n> > +       new=$(git rev-parse --git-dir)/put-index.tmp\n> > +       cp \"$old\" \"$new\" &&\n> > +       GIT_INDEX_FILE=$new git checkout \"$@\"\n> > +       status=$?\n> > +       rm -f \"$new\"\n> > +       exit $status\n> > +}\n> > +\n> > +case \"$(type_of \"$from\"),$(type_of \"$to\")\" in\n> > +*,commit)\n> > +       die \"You can't modify an existing commit.\" ;;\n> > +index,index)\n> > +       die \"You can't move content from the index on top of itself.\" ;;\n> > +worktree,index)\n> > +       exec git add $patch -- \"$@\" ;;\n> > +commit,index)\n> > +       exec git reset $patch \"$from\" -- \"$@\" ;;\n> > +index,worktree)\n> > +       exec git checkout $patch -- \"$@\" ;;\n> > +worktree,worktree)\n> > +       die \"You can't move content in the worktree on top of itself.\" ;;\n> > +commit,worktree)\n> > +       worktree_checkout $patch \"$from\" -- \"$@\" ;;\n> > +esac\n> >\n> >\n> > As you can see, this handles only three typoes of locations: the\n> > worktree, the index, and an arbitrary commit (really a tree-ish).\n>\n> Last time we were stuck at the magic keywords INDEX and WORKTREE. What\n> if we sort of follow scp naming convention:\n>\n>  - Normal paths are working tree's paths\n>  - Paths with a colon in it are in \"remote\" locations (index or a\n> tree). The part before colon specifies the location.\n>\n> We could have:\n>\n> git put <src> [<src>...] <dst>\n> git put <src> [<src>...] <dst> -- <pathspec>\n>\n> Where <src> and <dst> could be\n>\n>  - <tree-ish> <colon> [<pathspec>]\n>  - [0-3] <colon> [<pathspec>]\n>  - <pathspec> (or plain path)\n>\n> In the first form, pathspec could be specified in <src>. If <dst> is\n> worktree, then \".\" would be enough (or path to repo's root to be more\n> strict). In the second form, no pathspec can be part of <src> nor\n> <dst> because they're at the end already.\n>\n> With this syntax we could have:\n>\n> git put 0:path/to/file.c . (or git put 0: path/to/file.c)\n>  -> copy file.c from index to worktree (at the same path \"path/to/file.c\")\n> git put path/to/file 0:\n>  -> copy file to index\n> git put HEAD: . -- path/\n>  -> checkout everything in path/ from HEAD\n>\n> I'm not sure how mutiple <src> should work, but there may be a use case for it.\n>\n> > Some other types I've thought of are:\n> > ...\n> >  - branches as destinations; obviously we can't change an existing\n> >    commit, but what about something like:\n> >\n> >      git put WORKTREE BRANCH:foo\n> >\n> >    to optionally create a new branch \"refs/heads/foo\" based on the\n> >    current HEAD, push changes into a temporary index that matches its\n> >    tip, and then making a new commit based on top.\n> >\n> >    This would serve a similar purpose to stashes, except that they\n> >    would be named and could operate as full branches. I would find it\n> >    useful for picking apart a mass of worktree changes into discrete\n> >    commits.\n> >\n> >  - allow multiple destinations, like\n> >\n> >     # equivalent to \"git checkout --\"\n> >     git put HEAD INDEX,WORKTREE\n>\n> These obviously do not work with the syntax I propose.\n> --\n> Duy\n"},{"id":"182965","messageId":"CACsJy8AB-6b_PMvyM7hRV3b=5o0Cn4CtosygUQOevTzVJhU=hg@mail.gmail.com","threadId":"27570","inReplyTo":"CADo4Y9iH+J-X-TdqTN2Y9KhQnprnCVvC4Xy6qhVHwsBRmsZUrg@mail.gmail.com","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2012-01-23T14:35:07Z","receivedAt":"2012-01-23T14:35:07Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Mon, Jan 23, 2012 at 8:53 PM, Michael Nahas <mike.nahas@gmail.com> wrote:\n> \"git put\" is \"git cp\".  It copies from one filesystem (or a snapshot\n> of a filesystem) to another filesystem.\n\nExactly.\n\n> Without multiple working directories, a modifiable \"stash\", or a\n> (useful) name for the filesystem referred to as\n> \"index\"/\"cache\"/\"staging area\", there is only one filesystem that the\n> command can write to: the (singular) working directory.\n\nNo there are two writable \"filesystems\": working directory and\n\"index/cache/staging area\"\n\n> So, \"git put <src filesystem> -- <path>\" is fine.  It will copy from\n> the path in the src filesystem to the path in the current working\n> directory.  I don't think the command \"put\" is a great name for that.\n> Since we already have some strange double-usage commands like \"git\n> checkout --\" and \"git reset --\", perhaps this should be \"git\n> cherry-pick --\".\n\nThe \"-- <path>\" thing may save you a few keystrokes when you want to\ncopy from more than one path(spec). The two below commands are\nequivalent\n\ngit put HEAD:a/ HEAD/b/ HEAD/c/ .\ngit put HEAD: . -- a/ b/ c/\n\nBut of course if you just need to copy from one pathspec to another\nplace, \"--\" syntax is redundant.\n\n> <rant>\n> But for my money, \"git cp\" is clearer and I'd love to get rid of the\n> user-confusing double-usage commands.  I'd replace \"git checkout --\"\n> with \"git cp NEXT WTREE -- <path>\" and replace \"git reset --\" with\n> \"git cp HEAD NEXT --\" where NEXT is the filesystem represented by the\n> \"index\"/\"cache\"/\"staging area\" and WTREE is an alias for the working\n> directory.\n> </rant>\n\nI thought of \"cp\" (naturally, I was driven by \"scp\" syntax as I said)\nand maybe if we think this through, we may be able to enhance cp to\nsupport \"remote locations\" (and --patch option). So \"put\" vs \"cp\" is\nnot important to me now. What I'd like to hear is whether the syntax\nmakes sense.\n\nMy \"hidden\" plan if this works out would be to deprecate (or\ndiscourage) everything in git-checkout except branch switching. I\ndon't have anything against git-reset. It's a kind of dangerous\ncommand from the start (while git-checkout is more user friendly) and\ncan stay that way. The new \"git <cp, put or whatever name>\" should\nfill 90% the needs for git-reset.\n-- \nDuy\n"},{"id":"182966","messageId":"CADo4Y9j5MwKr+rWza0ncLWuthY6x+s68CQYbY2+c8-E5pAa=Sw@mail.gmail.com","threadId":"27570","inReplyTo":"CACsJy8AB-6b_PMvyM7hRV3b=5o0Cn4CtosygUQOevTzVJhU=hg@mail.gmail.com","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Michael Nahas","fromEmail":"mike.nahas@gmail.com","sentAt":"2012-01-23T14:56:37Z","receivedAt":"2012-01-23T14:56:37Z","isPatch":true,"sender":{"key":"mike.nahas@gmail.com","avatar":null},"body":"Hi Duy,\n\nI've contributed no code to git.  I've come up with plenty of ideas,\nwhich seem to have gotten little traction.\n\nYour ideas are similar to mine (and others), but the last attempt to\nget them into git did not accomplish anything.  I don't know how much\nwork you have done on git, but before participating with git again, I\nsuggest you look at why the last attempt failed and we ask an\nexperienced person how things work.\n\nIt obviously isn't the design-first-then-find-a-willing-programmer of\nthe project I ran.  I don't know if it's the IETF's \"running code and\na general consensus\".  The only thing I've found is that people did\nnot want to discuss theory.  (I believe the feeling is that theory is\nonly worthy of DARCS.)  I also got the feeling that improving the user\ninterface (e.g., replacing \"git checkout --\" and \"git reset --\") was\nnot a priority.\n\nSo, please plan out a strategy before recruiting me to help push this\nidea forward.\n\nMike\n\n\nOn Mon, Jan 23, 2012 at 9:35 AM, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:\n>\n> On Mon, Jan 23, 2012 at 8:53 PM, Michael Nahas <mike.nahas@gmail.com> wrote:\n> > \"git put\" is \"git cp\".  It copies from one filesystem (or a snapshot\n> > of a filesystem) to another filesystem.\n>\n> Exactly.\n>\n> > Without multiple working directories, a modifiable \"stash\", or a\n> > (useful) name for the filesystem referred to as\n> > \"index\"/\"cache\"/\"staging area\", there is only one filesystem that the\n> > command can write to: the (singular) working directory.\n>\n> No there are two writable \"filesystems\": working directory and\n> \"index/cache/staging area\"\n>\n> > So, \"git put <src filesystem> -- <path>\" is fine.  It will copy from\n> > the path in the src filesystem to the path in the current working\n> > directory.  I don't think the command \"put\" is a great name for that.\n> > Since we already have some strange double-usage commands like \"git\n> > checkout --\" and \"git reset --\", perhaps this should be \"git\n> > cherry-pick --\".\n>\n> The \"-- <path>\" thing may save you a few keystrokes when you want to\n> copy from more than one path(spec). The two below commands are\n> equivalent\n>\n> git put HEAD:a/ HEAD/b/ HEAD/c/ .\n> git put HEAD: . -- a/ b/ c/\n>\n> But of course if you just need to copy from one pathspec to another\n> place, \"--\" syntax is redundant.\n>\n> > <rant>\n> > But for my money, \"git cp\" is clearer and I'd love to get rid of the\n> > user-confusing double-usage commands.  I'd replace \"git checkout --\"\n> > with \"git cp NEXT WTREE -- <path>\" and replace \"git reset --\" with\n> > \"git cp HEAD NEXT --\" where NEXT is the filesystem represented by the\n> > \"index\"/\"cache\"/\"staging area\" and WTREE is an alias for the working\n> > directory.\n> > </rant>\n>\n> I thought of \"cp\" (naturally, I was driven by \"scp\" syntax as I said)\n> and maybe if we think this through, we may be able to enhance cp to\n> support \"remote locations\" (and --patch option). So \"put\" vs \"cp\" is\n> not important to me now. What I'd like to hear is whether the syntax\n> makes sense.\n>\n> My \"hidden\" plan if this works out would be to deprecate (or\n> discourage) everything in git-checkout except branch switching. I\n> don't have anything against git-reset. It's a kind of dangerous\n> command from the start (while git-checkout is more user friendly) and\n> can stay that way. The new \"git <cp, put or whatever name>\" should\n> fill 90% the needs for git-reset.\n> --\n> Duy\n"},{"id":"182975","messageId":"7vaa5e9tn2.fsf@alter.siamese.dyndns.org","threadId":"27570","inReplyTo":"CADo4Y9j5MwKr+rWza0ncLWuthY6x+s68CQYbY2+c8-E5pAa=Sw@mail.gmail.com","subject":"Re: [RFC/PATCH] git put: an alternative to add/reset/checkout","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2012-01-23T18:10:57Z","receivedAt":"2012-01-23T18:10:57Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Michael Nahas <mike.nahas@gmail.com> writes:\n\n> It obviously isn't the design-first-then-find-a-willing-programmer of\n> the project I ran. I don't know if it's the IETF's \"running code and\n> a general consensus\".\n\nThese two are not necessarily incompatible.\n\nA proposed new feature needs to be explained well, describing in what\nsituation it will help what kind of users and without hurting others and\nwhy it is a worthy addition.\n\nWe require a general consensus that any proposed change is a worthy\naddition, and a working code is often a good addition to help us reaching\none, because people can guess what is being proposed even when the idea is\npresented poorly. A poorly presented idea without working code often fares\nno better than just a handwaving with crazy talk, as you fail to make\nothers realize what you are trying to achieve.\n\nBut working code is not a requirement to present good ideas. It just helps\nto add clarity to it.\n"}]}