Hello,
I am not sure this is the best place to write about this. Anyway,
we just switched a couple of repositories to git (from svn) here
at work and one thing people find annoying is a pull into
a dirty directory. Before the "stash" feature it was even worse
but now we can type:
git stash
git pull
git stash apply
But isn't that something we should be able to specify to the "pull"
command ? Additionally and if I am not mistakn, those commands will
create "dangling" commits and blobs. So one has to execute:
git prune
Is there an "easier" way to pull into a dirty directory ? I am
asking this to make sure I understand the problem and not
because I find it annoying to type those 4 commands to perform
a pull (although some of my colleagues do find that annoying :).
For now, I am recommanding to my colleagues to commit very often
(even unfinished changes), pull, and then rebase the commits into
a more meaningful commit before pushing. Which seems to be a good
practice anyway,
Thank you for git,
- Aghiles.
ps; if someone is interested to hear what is the general opinion
on switching to git from svn in our company, I could elaborate.
-
Yes, please. And how did you manage to convince them to switch, if possible: there are still some suckers here trying to do the same to their colleagues. -
Yes you are right. By the way, in the context of merging into a dirty tree, "git stash clear" seems to be a dangerous command: there is a risk of loosing all your changes without a question asked! I know unix is a harsh world but ... - Aghiles. -
Be *very* careful, because it's worse than that. If you run, say, `git stash clean', instead of `clear' (that's the sort of typo that quickly slips through), then it will stash all your changes in a new stash named "clean". Once you realize you made a typo, you will most probably correct it and run `git stash clear' but... Oops, you just wiped your changes that were in the "clean" stash. That happened to me and other people I know, so now I'm utterly cautious when I start a command with "git stash". As far as I remember, a patch was proposed to change this mis- behavior of "git stash" (one could argue that it's a PEBCAK issue, but I really think this command is *way* too dangerous) but I don't think it's been accepted at this time. Cheers, -- Benoit Sigoure aka Tsuna EPITA Research and Development Laboratory
Hello, I would love it if for once in the git world, there were a pair of commands that would do the exact opposite of each other and where the naive newbie (me) would immediately recognize that from their names: git stash push git stash pop Both applied in this order should be a no-op on both the working tree, the index, and also the stash. There's room for extensions (pop --keep-stash to not remove the stashed information), explicit naming of stashes, doing multiple pops at once, and so on. Please don't add more of the git-push/git-pull, git-add/git-rm unsymmetrical interfaces. Even if they're perfectly clear to git intimates, each one of them takes precious extra time to learn due to this lack of symmetry. Since I simply don't have the time resources to just implement that, I'll thank you for your attention and go back to lurking mode now. Thanks, Ralf -
Hi, You might as well be honest, and say that they are not time constraints, but lack of motivation. There is -- still! -- the patch "Teach "git reflog" a subcommand to delete single entries" in "pu" to delete single reflogs (and being in "pu" means it is only a fetch and a cherry-pick away). Implementing that feature would be a piece of cake, but I will not do it, since _you_ want it, not _I_. In spite of that, I implemented that reflog deleting, which was the hardest part of the exercise. So, out, out with you, out of lurking mode! Ciao, Dscho -
No. I will not do it, because the marginal cost of getting to know not only git but also its source is too high for my precious time ATM. Maybe next year. Will you do it for me if I buy you some beer? If I promise to (continue to) proofread git documentation for a couple of months? If I do more audit of git's shell code, searching for nonportable constructs? Or if I promise to try to help you with any autotools doesn't sound like it, but I would understand very well if it needed that. Please consider that division of work really can be advantageous and that not all git users want to be or can be developers at all times. Cheers, Ralf -
no it's a command issue. git stash <random non command name> should _NOT_ be an alias to git stash save <random name>. Either the command should be mandatory _or_ it should be a long option to avoid such kind of conflicts. It's just a bad ui design. --=20 =C2=B7O=C2=B7 Pierre Habouzit =C2=B7=C2=B7O madcoder@debia= n.org OOO http://www.madism.org
Complain to STDERR unless 'git stash save' is explicitly used. This is in preparation for completely disabling the "default save" behavior of the command in the future. Signed-off-by: Brian Downing <bdowning@lavos.net> --- Documentation/git-stash.txt | 9 ++++----- git-stash.sh | 8 +++++++- t/t3903-stash.sh | 14 +++++++++++++- 3 files changed, 24 insertions(+), 7 deletions(-) diff --git a/Documentation/git-stash.txt b/Documentation/git-stash.txt index c0147b9..61cf95d 100644 --- a/Documentation/git-stash.txt +++ b/Documentation/git-stash.txt @@ -9,7 +9,7 @@ SYNOPSIS -------- [verse] 'git-stash' (list | show [<stash>] | apply [<stash>] | clear) -'git-stash' [save] [message...] +'git-stash' save [message...] DESCRIPTION ----------- @@ -39,8 +39,7 @@ OPTIONS save:: Save your local modifications to a new 'stash', and run `git-reset - --hard` to revert them. This is the default action when no - subcommand is given. + --hard` to revert them. list:: @@ -119,7 +118,7 @@ perform a pull, and then unstash, like this: $ git pull ... file foobar not up to date, cannot merge. -$ git stash +$ git stash save $ git pull $ git stash apply ---------------------------------------------------------------- @@ -147,7 +146,7 @@ You can use `git-stash` to simplify the above, like this: + ---------------------------------------------------------------- ... hack hack hack ... -$ git stash +$ git stash save $ edit emergency fix $ git commit -a -m "Fix in a hurry" $ git stash apply diff --git a/git-stash.sh b/git-stash.sh index f39bd55..a8b854a 100755 --- a/git-stash.sh +++ b/git-stash.sh @@ -1,7 +1,7 @@ #!/bin/sh # Copyright (c) 2007, Nanako Shiraishi -USAGE='[ | list | show | apply | clear]' +USAGE='[save | list | show | apply | clear]' SUBDIRECTORY_OK=Yes . git-sh-setup @@ -223,6 +223,12 @@ help | usage) if test $# -gt 0 && test "$1" = save then shift + else + cat >&2 <<EOF +'git ...
Having 'git stash random stuff' actually stash changes is poor
user interface, due to the likelyhood of misspelling another legitimate
argument. Require an explicit 'save' command instead.
Signed-off-by: Brian Downing <bdowning@lavos.net>
---
This commit can be applied on top of the previous whenever it
is decided "enough time" has passed for the hard behavior change
of "git stash" to take place.
git-stash.sh | 16 +++++-----------
t/t3903-stash.sh | 4 ++--
2 files changed, 7 insertions(+), 13 deletions(-)
diff --git a/git-stash.sh b/git-stash.sh
index a8b854a..e900d40 100755
--- a/git-stash.sh
+++ b/git-stash.sh
@@ -219,17 +219,11 @@ create)
help | usage)
usage
;;
-*)
- if test $# -gt 0 && test "$1" = save
- then
- shift
- else
- cat >&2 <<EOF
-'git stash [message...]' is deprecated, please use
-'git stash save [message...]' instead.
-
-EOF
- fi
+save)
+ shift
save_stash "$*" && git-reset --hard
;;
+*)
+ usage
+ ;;
esac
diff --git a/t/t3903-stash.sh b/t/t3903-stash.sh
index adfac4b..4896da0 100755
--- a/t/t3903-stash.sh
+++ b/t/t3903-stash.sh
@@ -73,13 +73,13 @@ test_expect_success 'unstashing in a subdirectory' '
git stash apply
'
-test_expect_success 'stash with no args' '
+test_expect_failure 'stash with no args' '
echo 7 > file &&
test_tick &&
git stash
'
-test_expect_success 'stash with bare message' '
+test_expect_failure 'stash with bare message' '
echo 8 > file &&
test_tick &&
git stash "a message"
--
1.5.3.5.1547.gf6d81-dirty
-
Can't we have these two? git-stash git-stash save [message...] 'git stash' without a message as an equivalent of 'git stash save' is still very handy. -- Hannes -
Ok, but I would prefer to see this made into at least a three-step process to ease the migration on users. I do not have any issue with a deprecation warning before the next big release (1.5.4?). The next step after this patch should not be the removal of "defalut save". Instead, introduce a boolean configuration, stash.defaultsave, that defaults to false. Without the configuration, disable the "default save" (and do not even mention the configuration variable, but do give the usage message listing the commands). But allow people to use the "default save" behaviour with the configuration to help existing users. You can do this in the same release as above if you want. Then you would finally drop the "default save" in the next big release after that "deprecation release". But not before that. BTW, I've been quietly rewriting git-stash in C. Be warned ;-) -
No arguments at all should not IMHO be deprecated, it's very useful, and is not ambiguous. The issue with git stash <random> is that if you thought you typed a command that doesn't in fact exists, you stash which is not what you meant _at all_. When you type `git stash` you certainly want to stash, and it's what it does. Here is how it should work: git-stash (list | show [<stash>] | apply [<stash>] | clear) git-stash [save <message>] --=20 =C2=B7O=C2=B7 Pierre Habouzit =C2=B7=C2=B7O madcoder@debia= n.org OOO http://www.madism.org
I think that people will use this a lot with the pull command and some
accidents will happen. I am of the opinion that the semantics of this
command must be changed.
Additionally, having "git stash [command]" and "git stash [argument]"
mixed together seems strange. One suggestion would be:
git stash store/add/create [stash-name]
git stash apply [stash-name]
git stash clear <stash-name> (accepts wildcards but no empty args)
...
- Aghiles.
-
I'm using: $ git config --global alias.update '!git stash && git pull && git stash apply' Then in a git repository just do: Would be nice to hear about that indeed. Pascal. -- --|------------------------------------------------------ --| Pascal Obry Team-Ada Member --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE --|------------------------------------------------------ --| http://www.obry.net --| "The best way to travel is by means of imagination" --| --| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595 -
I wonder how this works, if the merge produces conflicts... Best regards Uwe -- Uwe Kleine-König http://www.google.com/search?q=1+year+in+days -
If you have conflicts it will not do the "git stash apply" as git pull will return with an error. So you'll need to fix the conflicts and do you the final git stash manually. Pascal. -- --|------------------------------------------------------ --| Pascal Obry Team-Ada Member --| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE --|------------------------------------------------------ --| http://www.obry.net --| "The best way to travel is by means of imagination" --| --| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595 -
You need to switch your mindset from centralized SVN workflow. The beauty of distributedness is that it redefines the meaning of "to commit". In distributed systems, the act of committing is purely checkpointing and it is not associated with publishing the result to others as centralized systems force you to. Stop thinking like "I need to integrate the changes from upstream into my WIP to keep up to date." You first finish what you are currently doing, at least to the point that it is stable, make a commit to mark that state, and then start thinking about what other people did. You may most likely do a "git fetch" followed by "git rebase" to update your WIP on top of the updated work by others. Once you get used to that, you would not have "a dirty directory" problem. -
I respectfully beg to differ. I think it is entirely reasonable, and not a sign of "centralized" mindset, to want to pull changes others have made into your dirty repository with a single command. Bill -
I agree, I have such needs at work. Here is how we (very informally) work: people push things that they believe could help other (a new helper function, a new module, a bug fix) in our master ASAP, but develop big complex feature in their repository and merge into master when it's ready. Very often we discuss some bugfix that is impeding people, or a most-wanted-API. Someone does the work, commits, I often want to merge master _directly_ into my current work-branch, because I want the fix/new-API/... whatever. I don't believe it's because we have a centralized repository that I have those needs, I would have the very same if I pulled changes directly from my colleagues repository. The reason why I need it at work is because there are some very vivid kind of changes, that only takes a couple of diff lines, and that you _need_ for your work to be completed. It's not really a matter of being fully up-to-date. Though to my delight, with the current tip-of-next git, I noticed that many rebase and pull work in a dirty tree now :) --=20 =C2=B7O=C2=B7 Pierre Habouzit =C2=B7=C2=B7O madcoder@debia= n.org OOO http://www.madism.org
How about merging just that "fix/new-API/... whatever" thing and not the whole master, which should be a complete mess by now? The way you explained it it looks like typical centralized workflow. -
No master only holds simple patches (few of them, typically half a Well I disagree, it's /part/ centralized. We have a two speed devel method, one that works the old-centralized way for quick fixes, and a more decentralized approach for big changes. It's a rather nice and useful middle ground for a company where all programmers are within earshot. --=20 =C2=B7O=C2=B7 Pierre Habouzit =C2=B7=C2=B7O madcoder@debia= n.org OOO http://www.madism.org
BitKeeper, for example, does a merge with a "dirty" directory. I am not saying that git should behave the same way but I think that this argument strengthens the point that it is not a "centralized repository" mindset. - Aghiles. -
Git does merge with dirty working directory. It just wont touch the changed files and stop merging if the merge requires it. -
Git does merge with a dirty directory too, but refuses to merge if it needs to *change* any individual dirty *files*. And that actually comes from one of the great strengths of git: in git (unlike just about any other SCM out there) you can - and are indeed expected to - resolve merges sanely in the working tree using normal filesystem accesses (ie your basic normal editors and other tools). That means that if there is a unresolved merge, you're actually expected to edit things in the same place where they are dirty. Which means that the merge logic doesn't want to mix up your dirty state and whatever merged state, because that is then not sanely resolvable. Now, I do think that we could relax the rule so that "files that are modified must be clean in the working tree" could instead become "files that actually don't merge _trivially_ must be clean in the working tree". But basically, if it's not a trivial merge, then since it's done in the working tree, the working tree has to be clean (or the merge would overwrite it). Doing a four-way merge is just going to confuse everybody. So we *could* probably make unpack-trees.c: treeway_merge() allow this. It's not totally trivial, because it requires that the CE_UPDATE be replaced with something more ("CE_THREEWAY"): instead of just writing the new result, it should do another three-way merge. So it's within the range of possible, but it's actually pretty subtle. The reason: we cannot (and *must*not*!) actually do the three-way merge early. We need to do the full tree merge in stage 1, and then only if all files are ok can we then check out the new tree. And we currently don't save the merge information at all. So to do this, we'd need to: - remove the "verify_uptodate(old, o); invalidate_ce_path(old);" in "merged_entry()", and actually *leave* the index with all three stages intact, but set CE_UPDATE *and* return success. - make check_updates() do the three-way merge of "original ...
I really think this is a good idea. It seems to me that the first "bad" surprise a svn/cvs/bk user will have is the result of a "git pull" command on a dirty tree. With the proposed change, and if I understand correctly: - users that are used to commit often and fetch into clean trees will never be bothered by this change. - users that are used to "update" often are expecting to resolve conflicts in their working copy anyway. In both cases git does not get in your way and everyone is happy. - Aghiles -
Hi, But the latter ones will likely not understand why all of a sudden their working tree has to be clean sometimes (when there was no trivial merge possible). Besides, I think it is not trivial to implement. Not my itch, Dscho -
Well, there will still be cases where people won't be happy. That said, all fast-forward cases (which is, I guess, a fairly common way of operating for anybody who has ever just uses anoncvs to track others) would be handled by the "three-way-merge dirty data for trivial merges". So even if it would only handle that special case (and it handles a *lot* of other cases too!) it probably would be useful to some people. That said, I still don't think I have the energy to actually try to do it. I do suspect it's not that hard, and I outlined where it would go, but it's really quite core and important code... IOW, this needs *lots* of deep thought and care. Linus -
I find it much more convenient to just fetch them. I'd rather see git-pull being given a --rebase option (which would ultimately mean teaching git-merge about it) to rebase already committed changes on top of the newly fetched tracking branch. It's being worked on, but rather slowly. -- Andreas Ericsson andreas.ericsson@op5.se OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231 -
Hi, git-pull learning about --rebase does not mean teaching git-merge about it. See my patch, which you (and others) failed to enthusiastically embrace, which is the sole reason it is stalled. Ciao, Dscho -
I must have missed it. Found the thread now though. Gonna try the patch in production for a while and see how it pans out. I'm curious about this hunk though. It seems unaffiliated with the --rebase option as such, but was still in the patch. Would you care to clarify? @@ -86,7 +95,6 @@ merge_head=$(sed -e '/ not-for-merge /d' \ case "$merge_head" in '') - curr_branch=$(git symbolic-ref -q HEAD) case $? in 0) ;; 1) echo >&2 "You are not currently on a branch; you must explicitly" -- Andreas Ericsson andreas.ericsson@op5.se OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231 -
Hi, No, it is not unaffiliated. If you go back to the patch, you will find that this line was not deleted, but moved to the start of git-rebase.sh. We need to know the branch name to get the config settings, and might just as well reuse the branch name for the merge_head case. Hth, Dscho -
Righto. I should learn to not write emails or read patches before 10am. Thanks for clarifying. -- Andreas Ericsson andreas.ericsson@op5.se OP5 AB www.op5.se Tel: +46 8-230225 Fax: +46 8-230231 -
I don't think wanting to pull in the middle of one's work has anything to do with centralized vs. decentralized, actually, though I do agree that it's a question of workflow. For maybe 80% of my work, I do things "the git way" (lots of little local commits) and only sync up with other people when I've reached a good stopping point. Those are cases where I'm working in isolation on a new feature or a fix and will publish it as a whole unit when I'm done. But the other 20% of the time, I'm working closely with another person. For example, I might be working with a front-end developer who is writing some nice snazzy JavaScript or Flash UI code to talk to my server-side code. And in that case, I really do want to be able to pull down his latest changes while I'm still in the middle of working on my own stuff, not least because it's only by testing with the real client -- where the button to invoke a particular piece of code on my side has just been added in the last 2 minutes -- that I can decide whether my work in progress is actually functional or not. (Unit tests only get you partway there.) In other words, for traditional open-source-style distributed development where each repository is an isolated island that goes off and does its own thing, ignoring the outside world, the recommended git workflow is totally appropriate. It's also appropriate for a lot of in-house non-distributed development. But for some classes of collaboration, where two or more people are essentially editing the same code base to work on the same feature and their changes are highly interdependent, that workflow is next to useless. There *is* no "I've gotten my code working and am ready to look at other people's changes now" stage until pretty late in the game. This kind of workflow happens a lot in commercial development in my experience. Before git-stash, I did a lot of "commit; fetch; rebase; reset" sequences to support this kind of tight ...
This is very nice actually and we absolutely understand what a commit means in the git world. Having the commit as a step before publishing is very helpful (although some concepts such One particular situation in which this might not apply is when two people work very closely on the same feature (as mentioned by Steve Grimm in this thread) and one needs the changes made by the other. This often happens when starting a new project, as it is our case now :) Thank you, - Aghiles. -
