git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [RFC/PATCH] git put: an alternative to add/reset/checkout

From
MNMichael Nahas <mike.nahas@gmail.com>
Date
Jan 23, 2012, 13:53 UTC
Message-ID
<CADo4Y9iH+J-X-TdqTN2Y9KhQnprnCVvC4Xy6qhVHwsBRmsZUrg@mail.gmail.com>
In-Reply-To
<CACsJy8BCGi3s8gXr4kk-u8tDWztV6ozg1Tap23Q=TxA5d9iL+g@mail.gmail.com>
On Mon, Jan 23, 2012 at 5:32 AM, Nguyen Thai Ngoc Duy <pclouds@gmail.com> wrote:
>
> (Bringing up an old thread)

"...thank you so much for bringing up such a painful subject. While you're at it, why don't you give me a nice paper cut and pour lemon juice on it."

"git put" is "git cp".  It copies from one filesystem (or a snapshot of a filesystem) to another filesystem.

Without multiple working directories, a modifiable "stash", or a (useful) name for the filesystem referred to as "index"/"cache"/"staging area", there is only one filesystem that the command can write to: the (singular) working directory.

So, "git put <src filesystem> -- <path>" is fine.  It will copy from the path in the src filesystem to the path in the current working directory.  I don't think the command "put" is a great name for that. Since we already have some strange double-usage commands like "git checkout --" and "git reset --", perhaps this should be "git cherry-pick --".

<rant> But for my money, "git cp" is clearer and I'd love to get rid of the user-confusing double-usage commands.  I'd replace "git checkout --" with "git cp NEXT WTREE -- <path>" and replace "git reset --" with "git cp HEAD NEXT --" where NEXT is the filesystem represented by the "index"/"cache"/"staging area" and WTREE is an alias for the working directory. </rant>

Still, good luck.  It's a useful addition even if it is "git cherry-pick --".
Mike
Show 178 quoted lines
>
>
> On Wed, Jun 8, 2011 at 3:06 AM, Jeff King <peff@peff.net> wrote:
> > ...
> > But another way to think about it is that commits, the index, and the
> > working tree are all "locations" with content. And one common operation
> > you may want to do is to move content from one spot to another, either
> > whole, by file, or by diff hunks. To a new user, knowing that "add" is
> > the command for moving content from thet working tree to the index does
> > not help them know which command to use to do the opposite content
> > movement.
> > ...
> > My idea is therefore to have a single command for moving content from
> > one location to another. You specify a source and a destination and get
> > a uniform interface for moving content.
> >
> > A proof-of-concept patch is below. Be aware that is meant to be
> > illustrative and is not well tested. Also, it is a minimal presentation
> > of the concept. Other "locations" may also be meaningful. I'll include
> > some ideas below the patch.
> >
> > ---
> >  Makefile   |    1 +
> >  git-put.sh |   70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 71 insertions(+), 0 deletions(-)
> >  create mode 100644 git-put.sh
> >
> > diff --git a/Makefile b/Makefile
> > index e40ac0c..4564506 100644
> > --- a/Makefile
> > +++ b/Makefile
> > @@ -368,6 +368,7 @@ SCRIPT_SH += git-merge-one-file.sh
> >  SCRIPT_SH += git-merge-resolve.sh
> >  SCRIPT_SH += git-mergetool.sh
> >  SCRIPT_SH += git-pull.sh
> > +SCRIPT_SH += git-put.sh
> >  SCRIPT_SH += git-quiltimport.sh
> >  SCRIPT_SH += git-rebase.sh
> >  SCRIPT_SH += git-repack.sh
> > diff --git a/git-put.sh b/git-put.sh
> > new file mode 100644
> > index 0000000..f673e14
> > --- /dev/null
> > +++ b/git-put.sh
> > @@ -0,0 +1,70 @@
> > +#!/bin/sh
> > +
> > +SUBDIRECTORY_OK=Yes
> > +OPTIONS_KEEPDASHASH=Yes
> > +OPTIONS_SPEC="\
> > +git put [options] <from> <to> [--] <file...>
> > +
> > +Move contents from one place to another, where <from> and <to> are one of:
> > +  1. A commit (e.g., master, HEAD~10, v1.7.5)
> > +  2. The special token INDEX to indicate git's index.
> > +  3. The special token WORKTREE to indicate the working directory.
> > +
> > +Options:
> > +--
> > +p            don't move whole files; use the patch interface
> > +"
> > +. git-sh-setup
> > +
> > +patch=
> > +while test $# != 0; do
> > +       case "$1" in
> > +       -p) patch=--patch ;;
> > +       --) shift; break ;;
> > +       *) usage ;;
> > +       esac
> > +       shift
> > +done
> > +test $# -lt 2 && usage
> > +
> > +from=$1; shift
> > +to=$1; shift
> > +test "$1" = "--" && shift
> > +
> > +type_of() {
> > +       case "$1" in
> > +       INDEX) echo index ;;
> > +       WORKTREE) echo worktree ;;
> > +       *) echo commit ;;
> > +       esac
> > +}
> > +
> > +# Checkout contents to worktree without munging the index in
> > +# between.
> > +worktree_checkout() {
> > +       old=$GIT_INDEX_FILE
> > +       test -z "$old" && old=$(git rev-parse --git-dir)/index
> > +       new=$(git rev-parse --git-dir)/put-index.tmp
> > +       cp "$old" "$new" &&
> > +       GIT_INDEX_FILE=$new git checkout "$@"
> > +       status=$?
> > +       rm -f "$new"
> > +       exit $status
> > +}
> > +
> > +case "$(type_of "$from"),$(type_of "$to")" in
> > +*,commit)
> > +       die "You can't modify an existing commit." ;;
> > +index,index)
> > +       die "You can't move content from the index on top of itself." ;;
> > +worktree,index)
> > +       exec git add $patch -- "$@" ;;
> > +commit,index)
> > +       exec git reset $patch "$from" -- "$@" ;;
> > +index,worktree)
> > +       exec git checkout $patch -- "$@" ;;
> > +worktree,worktree)
> > +       die "You can't move content in the worktree on top of itself." ;;
> > +commit,worktree)
> > +       worktree_checkout $patch "$from" -- "$@" ;;
> > +esac
> >
> >
> > As you can see, this handles only three typoes of locations: the
> > worktree, the index, and an arbitrary commit (really a tree-ish).
>
> Last time we were stuck at the magic keywords INDEX and WORKTREE. What
> if we sort of follow scp naming convention:
>
>  - Normal paths are working tree's paths
>  - Paths with a colon in it are in "remote" locations (index or a
> tree). The part before colon specifies the location.
>
> We could have:
>
> git put <src> [<src>...] <dst>
> git put <src> [<src>...] <dst> -- <pathspec>
>
> Where <src> and <dst> could be
>
>  - <tree-ish> <colon> [<pathspec>]
>  - [0-3] <colon> [<pathspec>]
>  - <pathspec> (or plain path)
>
> In the first form, pathspec could be specified in <src>. If <dst> is
> worktree, then "." would be enough (or path to repo's root to be more
> strict). In the second form, no pathspec can be part of <src> nor
> <dst> because they're at the end already.
>
> With this syntax we could have:
>
> git put 0:path/to/file.c . (or git put 0: path/to/file.c)
>  -> copy file.c from index to worktree (at the same path "path/to/file.c")
> git put path/to/file 0:
>  -> copy file to index
> git put HEAD: . -- path/
>  -> checkout everything in path/ from HEAD
>
> I'm not sure how mutiple <src> should work, but there may be a use case for it.
>
> > Some other types I've thought of are:
> > ...
> >  - branches as destinations; obviously we can't change an existing
> >    commit, but what about something like:
> >
> >      git put WORKTREE BRANCH:foo
> >
> >    to optionally create a new branch "refs/heads/foo" based on the
> >    current HEAD, push changes into a temporary index that matches its
> >    tip, and then making a new commit based on top.
> >
> >    This would serve a similar purpose to stashes, except that they
> >    would be named and could operate as full branches. I would find it
> >    useful for picking apart a mass of worktree changes into discrete
> >    commits.
> >
> >  - allow multiple destinations, like
> >
> >     # equivalent to "git checkout --"
> >     git put HEAD INDEX,WORKTREE
>
> These obviously do not work with the syntax I propose.
> --
> Duy
Previous: Nguyen Thai Ngoc DuyNext: Nguyen Thai Ngoc Duy
Message 15 of 18 in “git put: an alternative to add/reset/checkout”
  1. git put: an alternative to add/reset/checkoutJeff King, Jun 7, 2011
  2. Junio C HamanoJun 7, 2011
  3. Jeff KingJun 7, 2011
  4. Michael NahasJun 8, 2011
  5. Jakub NarebskiJun 8, 2011
  6. Matthieu MoyJun 8, 2011
  7. Jeff KingJun 8, 2011
  8. Matthieu MoyJun 8, 2011
  9. Jakub NarebskiJun 8, 2011
  10. Matthieu MoyJun 8, 2011
  11. Jakub NarebskiJun 8, 2011
  12. Nguyen Thai Ngoc DuyJun 10, 2011
  13. Nguyen Thai Ngoc DuyJun 8, 2011
  14. Nguyen Thai Ngoc DuyJan 23, 2012
  15. Michael NahasJan 23, 2012
  16. Nguyen Thai Ngoc DuyJan 23, 2012
  17. Michael NahasJan 23, 2012
  18. Junio C HamanoJan 23, 2012

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.