Re: The git newbie experience

4 messages, 3 authors, 2016-06-15 · open the first message on its own page

Re: The git newbie experience

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:26

Shawn Pearce [off-list ref] writes:
quoted
I'd rather do that with a diff file that can be used to do a
3-way (see how rebase does it with --full-index diff with am -3).
No point creating and forgetting to remove a throw away branch
and getting more complaints.
How is a quick stash different from a topic branch?
The original version of my message in response to TV looked like
this.

 - Jack is a beginning user of git and does not (want to) understand
   the index (right now).

 - Jack works on branch X, say his HEAD points to X1. He has an edited,
   uncommitted files with the names A, B and C.

 - Jack wants to pull new changes made by others to his branch.
   But "git merge" invoked from "git pull" says he needs to stash
   away the local changes to do the merge.

 - Jack stashes away what he has been working on and cleans up
   his mess.

   git checkout -b stash ;# risks error when "stash" exists
   git commit -a -m 'Stashing WIP'
   git checkout master ;# assuming that was where he was

 - Jack then pulls.  There are merge conflicts in files D, E, ..., Z.

 - Jack resolves the merge conflicts and is ready to commit the resulting
   merge. Note files A, B and C do not have his unfinished work.

   There is no "if Jack does this or that" problem; he says "git
   commit -a" because that is the only "commit" command he knows
   about.

 - Jack then reapplies what he stashed away, and keeps working.

   git pull . --no-commit stash
   git branch -D stash

You have to teach the new user to (1) name something, only to
immediately discard it when he returns to what he was in the
middle of, (2) remember to clean up the temporary thing once he
is done lest he forgets to clean it up (and common names like
"stash", "tmp" will be reused by accident causing grief next
time he needs to do another stash), and (3) use of --no-commit
pull.

On the other hand, "git stash/unstash" workflow would be quite
simple:

	$ git stash >my.precious.state
        ... do whatever you want to deviate to
        $ git unstash <my.precious.state

Merge resolve might be needed while unstashing, but 
we are talking about pulling somebody else's work in "do
whatever" part, so that is something the user knows how to
perform anyway.

A quick and dirty stash implementation would go like this:

Stash is easy.

        #!/bin/sh
        # git stash
        git diff --binary HEAD
        git reset --hard

Unstash is a bit involved.

        #!/bin/sh
        # git unstash
        . git-sh-setup
        O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
        O_DIR=`cd "$GIT_DIR" && pwd`
        stash="$O_DIR/.stash$$"
        rm -fr "$stash.*"
        trap 'rm -rf $stash.*' 0
        cat >"$stash.patch"
        git-apply -z --index-info <"$stash.patch" >"$stash.list"
        GIT_INDEX_FILE="$stash.index"  \
        GIT_OBJECT_DIRECTORY="$O_OBJECT" \
        (
                mkdir -p "$stash.tmp" &&
                git-update-index -z --index-info <"$stash.list" &&
                git-write-tree >"$stash.base" &&
                cd "$stash.tmp" &&
                git-apply --binary --index <"$stash.patch" &&
                git-write-tree >"$stash.his"
        )
        his_tree=$(cat "$stash.his")
        orig_tree=$(cat "$stash.base")
        rm -fr "$stash.*"
        git-merge-resolve $orig_tree -- HEAD $his_tree

This is essentially the core of "am -3" logic; if you are going
to use this for real, you would probably want to see if the
patch applies cleanly before falling back on the three-way
merge, though.

Re: The git newbie experience

From: Carl Baldwin <hidden>
Date: 2016-06-15 22:42:26

Junio,

This seems a lot like what I tried to do with git-undo/git-redo quite a
while back.

My implementation actually wrote the working file state into the object
store as a tree and stored a reference to the tree under something like
.git/refs/undo (or .git/refs/stash).  Redo was a simple merge of this
tree back onto the current working files.

I think I would like something like this better than the 'generate
binary patch and reapply the patch later.

If these commands were added to git I think they would be better if the
commands chose a temporary branch name, committed the current state to
that branch and did everything else that someone more experienced would
do using branches having chosen a temporary branch name.

The redo or unstash operation could just pick the most recent tempory
branch name (top of stack) and merge changes into the working copy.

Carl

On Mon, May 15, 2006 at 01:39:08AM -0700, Junio C Hamano wrote:
Shawn Pearce [off-list ref] writes:
quoted
quoted
I'd rather do that with a diff file that can be used to do a
3-way (see how rebase does it with --full-index diff with am -3).
No point creating and forgetting to remove a throw away branch
and getting more complaints.
How is a quick stash different from a topic branch?
The original version of my message in response to TV looked like
this.

 - Jack is a beginning user of git and does not (want to) understand
   the index (right now).

 - Jack works on branch X, say his HEAD points to X1. He has an edited,
   uncommitted files with the names A, B and C.

 - Jack wants to pull new changes made by others to his branch.
   But "git merge" invoked from "git pull" says he needs to stash
   away the local changes to do the merge.

 - Jack stashes away what he has been working on and cleans up
   his mess.

   git checkout -b stash ;# risks error when "stash" exists
   git commit -a -m 'Stashing WIP'
   git checkout master ;# assuming that was where he was

 - Jack then pulls.  There are merge conflicts in files D, E, ..., Z.

 - Jack resolves the merge conflicts and is ready to commit the resulting
   merge. Note files A, B and C do not have his unfinished work.

   There is no "if Jack does this or that" problem; he says "git
   commit -a" because that is the only "commit" command he knows
   about.

 - Jack then reapplies what he stashed away, and keeps working.

   git pull . --no-commit stash
   git branch -D stash

You have to teach the new user to (1) name something, only to
immediately discard it when he returns to what he was in the
middle of, (2) remember to clean up the temporary thing once he
is done lest he forgets to clean it up (and common names like
"stash", "tmp" will be reused by accident causing grief next
time he needs to do another stash), and (3) use of --no-commit
pull.

On the other hand, "git stash/unstash" workflow would be quite
simple:

	$ git stash >my.precious.state
        ... do whatever you want to deviate to
        $ git unstash <my.precious.state

Merge resolve might be needed while unstashing, but 
we are talking about pulling somebody else's work in "do
whatever" part, so that is something the user knows how to
perform anyway.

A quick and dirty stash implementation would go like this:

Stash is easy.

        #!/bin/sh
        # git stash
        git diff --binary HEAD
        git reset --hard

Unstash is a bit involved.

        #!/bin/sh
        # git unstash
        . git-sh-setup
        O_OBJECT=`cd "$GIT_OBJECT_DIRECTORY" && pwd`
        O_DIR=`cd "$GIT_DIR" && pwd`
        stash="$O_DIR/.stash$$"
        rm -fr "$stash.*"
        trap 'rm -rf $stash.*' 0
        cat >"$stash.patch"
        git-apply -z --index-info <"$stash.patch" >"$stash.list"
        GIT_INDEX_FILE="$stash.index"  \
        GIT_OBJECT_DIRECTORY="$O_OBJECT" \
        (
                mkdir -p "$stash.tmp" &&
                git-update-index -z --index-info <"$stash.list" &&
                git-write-tree >"$stash.base" &&
                cd "$stash.tmp" &&
                git-apply --binary --index <"$stash.patch" &&
                git-write-tree >"$stash.his"
        )
        his_tree=$(cat "$stash.his")
        orig_tree=$(cat "$stash.base")
        rm -fr "$stash.*"
        git-merge-resolve $orig_tree -- HEAD $his_tree

This is essentially the core of "am -3" logic; if you are going
to use this for real, you would probably want to see if the
patch applies cleanly before falling back on the three-way
merge, though.


-
To unsubscribe from this list: send the line "unsubscribe git" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
-- 
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
 Carl Baldwin                        RADCAD (R&D CAD)
 Hewlett Packard Company
 MS 88                               work: 970 898-1523
 3404 E. Harmony Rd.                 work: Carl.N.Baldwin@hp.com
 Fort Collins, CO 80525              home: Carl@ecBaldwin.net
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

Re: The git newbie experience

From: Carl Worth <hidden>
Date: 2016-06-15 22:42:26

On Mon, 15 May 2006 01:39:08 -0700, Junio C Hamano wrote:
 - Jack stashes away what he has been working on and cleans up
   his mess.

   git checkout -b stash ;# risks error when "stash" exists
   git commit -a -m 'Stashing WIP'
   git checkout master ;# assuming that was where he was
I really like the proposal made elsewhere to implement a new:

	commit -b <newbranch>

which would then allow for a single command to achieve at least the
first two commands above:

	git commit -a -b stash -m 'Stashing WIP'

It might even make sense for this command to effectively perform all
three of the above commands. That is, should "commit -b" also checkout
the newly created branch or should it leave HEAD unchanged. I'm not
sure.
You have to teach the new user to (1) name something, only to
immediately discard it when he returns to what he was in the
middle of, (2) remember to clean up the temporary thing once he
is done lest he forgets to clean it up (and common names like
"stash", "tmp" will be reused by accident causing grief next
time he needs to do another stash), and (3) use of --no-commit
pull.
I threw out a simple git-stash earlier, (which stashed to a branch
rather than to a file). I've spent some time using it, and am now
quite sure it's the wrong thing, and the above problems outline the
defect quite well:

1) Naming.

   Here, git-stash is doing too much. I prefer the idea of a stash
   command using a branch rather than a patch file, (and allowing one
   stash per branch rather than one stash per repository). But the
   namespace of branches is something the user owns, and we should
   avoid adding commands that steal from it unnecessarily. So my
   git-stash fails on this point, while "commit -b <newbranch>" is
   much better.

2) Cleanup and --no-commit pull

   Here, git-stash is doing too little. It's really only performing
   one piece of what needs to be done in order to switch back and
   forth between different topics of work.

So here are my thoughts on what I'd like instead:

In git, a branch is what we use to name a topic of work.

Historically, a branch has been extremely lightweight, (a name and
reference to a parent for subsequent commits). But there's been a
recent trend (in proposals at least) to add other, useful things to a
branch, (as in the discussions of branch-specific configuration).

In my work, I've found that the uncommitted state of my working tree
is something that I associate very strongly with my "current topic"
and expect the branch-changing commands respected that.

In particular, when using checkout to change branches, unless I've
specifically stated with "-m" that I want to carry my changes along, I
would like git to stash my working tree "into" the branch I'm
switching away from.

Similarly, when switching to a branch, I'd like to have the working
tree restored to what it was the last time I switched away from that
branch.

Does that seem unreasonable to anyone?

The only snag I've imagined is that when using "checkout -m" to switch
to a branch that also had a stashed working tree, then there's a merge
to be performed and that could obviously conflict. I've intentionally
not mentioned how the stashing/restoring should be implemented, since
the user shouldn't care. But a merge conflict is one case where the
implementation might leak out to the user. The wimpy thing to do would
be to refuse to allow "checkout -m" to a branch with stashed changes.

-Carl

Re: The git newbie experience

From: Junio C Hamano <hidden>
Date: 2016-06-15 22:42:26

Carl Baldwin [off-list ref] writes:
My implementation actually wrote the working file state into the object
store as a tree and stored a reference to the tree under something like
.git/refs/undo (or .git/refs/stash).  Redo was a simple merge of this
tree back onto the current working files.

I think I would like something like this better than the 'generate
binary patch and reapply the patch later.
When you think of the "binary patch" as a human readable
representation of your (hierarchical set of) tree objects, you
would realize that these two approaches aren't that much
different at the tree merge level, and it's just a matter of
which representation is more convenient and human readable.

Pros and cons I see are:

 * Branch approach needs to teach users only one thing -- create
   a branch, merge with it, throw it away.  Which is something
   the user needs to know anyway, so it is a plus.

 * Branch approach needs to store a full postimage tree and the
   base commit (so you can use it as a merge base); the
   postimage tree includes paths that are not involved in the
   change being stashed.

 * Patch records only the object names of paths that are relevant
   to the stash.  Instead of keeping the full postimage tree, it
   creates one on the fly when you actually do the unstashing.

 * Patch is human readable and can be used for purposes other
   than falling back to a three-way merge.  When cleanly applies
   apply + write-tree is faster than a tree merge.

 * Patch could be verbose if the change being stashed is large;
   after all the primary information used are the object names
   recorded on the "index" lines and the patch text itself is a
   waste from storage point of view.  This is a disadvantage of
   the "patch" approach, but its readability might offset it.
   If a change being stashed is large, the user had better be
   doing it on a separate topic branch anyway, so this might not
   be a big issue.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help