Hacker News new | past | comments | ask | show | jobs | submit login

> No. Your WIP commit will always land at the end. Anything you pull will rebase to before your WIP commit.

I was talking about the non-rebase version.

You didn't address the rest of my post: there are other cases. This will work for that particular case, but it's not a general-purpose solution.

If I have branch X with config changes, and coworker wants me to switch to branch Y but I still want my config changes, what do I do?




Stash is not a general purpose solution. You don't ever need to stash. There is nothing you can do with stashes that you can't do with core git commands, and the reverse is not true. Git could eliminate the stash command tomorrow without any loss of functionality.

What if you already committed your config changes to branch X, and your coworker wants them in Y? What if you you're working along and you have commits, staged changes, unstaged changes, and you need to branch 3 commits ago instead? Stash doesn't help with either of those, and the workflow I'm advocating - just use commits and branches for temporary work - does.

Stash really only helps you if you don't like to commit often, and you spend most of your time with unstaged changes in your working tree. Nothing wrong with that, if that's how you like to work, but I think if you spend some time getting used to committing more frequently you may find it much more flexible and much safer and more forgiving than trying to keep everything straight in the working tree alone.

If you have uncommitted changes in X, and you want in Y instead, then you can:

  $ git checkout Y
  $ git commit -am "config changes"
If you get merge conflicts, or if you want to keep the change in X too, you can:

  $ git commit -am "config changes"
  $ git checkout Y
  $ git cherry-pick X
The first case is fewer steps than stash, the second is just as easy as stash.

Popping a stash and cherry-picking a commit have the same process if there's a merge conflict, except that with a commit, you have undo capability if you merge incorrectly, and you have a safety net if you get lost or screw up in the middle of the resolution. With stash, you're stuck with a bad merge, and if you lose your stash -- and it happens -- you have to hunt for it by searching for dangling blobs.

You made a big deal out of having to create and remember and lookup hashes, and I don't see that as being an issue at all, and it's not a problem in my experience. You're comparing this to stash, after all, and stash only works on uncommitted changes, so there is never a case where you'll need a hash, because the stash equivalent is always at the tip of the branch, you can always use the branch name instead of a hash.


I didn't call it a general purpose solution in that context, nor did I call it a general purpose solution for everything. I am saying that I needed a general purpose solution for a situation that occurs often in many variants. For my situation, without stash, that was creating a commit and cherry-picking it places. Stash makes that case a lot easier to manage.

I don't use stash for cases where it doesn't make sense. I use stash for cases where, for me, it makes sense. For a special set of config changes that are never pushed. They're not part of my usual work, they're config changes. In this context, your 2nd paragraph makes no sense. I don't have to arbitrarily choose one or the other "workflow", I use both, and I simply use stash for the general case of reapplying configs on random branches. There are other ways to do it but they all require more headspace and are harder to track than stash and stash pop.

I'm not saying I need to stash or that I can't do it without stash. Have you not seen my earlier post?

It has nothing to do with being comfortable with commits. I'm already comfortable with commits. I've even said, before, that I did it with commits. It's just slower to do it with commits, and it means I have to manage commits for something I'll never, ever push. Every time I make something a commit, that's extra work for me later to make sure I don't push it out. If I make commits after that commit it's extra work for me to rebase it.

I don't put things in my stash where I care about a bad merge with them or that I'm even going to bother searching for the blob, I'll just redo the changes if that ever happens, because they're minor. They're things like: "Point to my database instead of the standard dev database". I just don't want to do them by hand every single time and I don't want to track a hash that changes every time I actually do want to change my configs.

You're the one making a big deal out of something, honestly, and you do not seem to be reading my posts very carefully because you're still making a lot of incorrect assumptions.


> You're the one making a big deal out of something, honestly, and you do not seem to be reading my posts very carefully because you're still making a lot of incorrect assumptions.

I'm sorry you feel like I wasn't listening to you. I was, and I read all your posts. You're absolutely right, I have made a big deal out of it. Despite the long discussion, I think we're in nearly full agreement, and FWIW, thank you for engaging.

I did misread your pull --rebase comment. I thought that was sorted now, but I'd be happy to address any other bad assumptions I'm making. It wasn't clear to me until just now that your config changes are small changes you never push. If you stated that before, I'm sorry.

Given your use case I agree with you, this is not an either-or proposition. And anyway, it's perfectly fine to leave all of this as my stupid opinion, and I don't want you to feel like you need to defend your use of stash. You clearly understand the issues and know how to use it.

In my mind, the only thing wrong with stash is how it's implemented, not its interface. I wish it had easier ways to recover, and I bet you did too that first time you used it.

Maybe the funniest part of this is I've been avoiding stash completely for years, but the threads for the last two days have convinced me there are some nice uses of stash that I may start adopting. A couple of them even increase safety! I do keep config changes around, and I like to name them with a tag or a branch, but I'm going to try stash and see if I prefer it.

Peace!


Well, I said at the very beginning:

> But that the thing - I never stash crucial code, just things like settings that are special to me and not other developers, so they'll probably never be pushed.

I don't know if that wasn't very clear.

Nothing wrong with opinions, there's a reason we share them, and I agree that stash could have probably been implemented a better way underneath. I have been recommended to use stash by another developer without any sort of warning, and with the implication that it's really safe and easy to use, which is rather funny in retrospect. Git's documentation page doesn't really talk about the dangers, either.

> Peace!

Indeed!


> $ git commit -am "config changes" > $ git checkout Y > $ git cherry-pick X

Sure, but then I also have to do:

    $ git checkout -
    $ git reset --hard HEAD~1
    $ git checkout -
which is a bunch of faff compared to the stash approach.

(side complaint: why doesn't "-" work for merge/cherry-pick/reset like it does for checkout?)


Huh? I don't get what you're doing there, or why you reset unstaged changes 3 times in a row... If you're trying to get rid of a commit, a single reset --hard will do. But why are you trying to get rid of a commit, and how is this more work that using stash? If you have unstaged changes you don't want, you have to reset either way, this is orthogonal to comparing stash vs no-stash workflows.

> why doesn't "-" work for merge/cherry-pick/reset like it does for checkout?

I don't know what a single dash does for you. On my git, I get a command line error with a single dash. Maybe you were thinking double-dash?

A double-dash is used to separate flags to your git command from path arguments, just in case a file you put on the command line starts with a dash. (Pro-tip: don't name files that start with dashes.) Running "git checkout -- ." at the top level of your repo will do the same thing as "git reset --hard HEAD".

Merge, cherry-pick and reset all work on refs, not on paths, so when you add a -- to one of those commands you may get an error like this:

  fatal: Cannot do hard reset with paths
The -- is optional to checkout, if the path is unambiguous. You can reset unstaged changes from your repo root by using "git checkout ."


> Huh? I don't get what you're doing there, or why you reset unstaged changes 3 times in a row... If you're trying to get rid of a commit, a single reset --hard will do. But why are you trying to get rid of a commit, and how is this more work that using stash? If you have unstaged changes you don't want, you have to reset either way, this is orthogonal to comparing stash vs no-stash workflows.

I accidentally made changes while on X when I wanted to make them on Y. I don't want to just "git checkout Y" in case that conflicts. If I do as you suggested and commit them (on X) and then cherry-pick that commit onto Y, I then have to go back to X to remove the commit I made, otherwise I have the changes on X as well.

> I don't know what a single dash does for you. On my git, I get a command line error with a single dash

"git checkout -" switches to the previous branch. Which is great, but it's frustrating that I can't do e.g. "git merge -" to merge the previous branch - logically that should be the same kind of thing.


> "git checkout -" switches to the previous branch.

OH, that's very nice, I want that. Guess I need to upgrade my git. Okay, that invalidates my entire previous post. Sorry! ;)

So, if you made changes on X but wanted them on Y...

The thing about the "git checkout Y" is that there's no harm in trying, and it'll work most of the time. If it does work, you only have to commit, and you're done in less time than it takes to stash & pop.

If you're just not the gambling type, here's one way to avoid branch ping-pong. I'm sure there are others.

  $ git checkout -b Z
  $ git commit -a "config changes"
  $ git checkout Y
  $ git cherry-pick Z
  $ git branch -D Z
I admit that's a tiny bit more work than with stash, in this case, but it's safer than stash, that's why I prefer it and advocate it. It is demonstrably harder to screw up if bad things happen in the middle. This workflow is also more general - you can use it if you have commits in X already. Stash doesn't help you there.

I've personally witnessed too many stash accidents. BUT, if you are comfortable with using fsck if anything goes wrong, you really have no reason to consider my opinion at all.

I'm painting a picture that is more anti-stash than I actually am. My main safety concern with stash is how it's implemented, not how easy it is. The git authors could have used something like the above commands under the hood to implement stash, but they chose to circumvent the reflog for reasons I don't know, and that choice leads to frequent accidents. Git is supposed to be your safety net, not something that gets you into trouble.

That said, a lot of people seem to think stash is many times easier than the alternative, and I think if you really look at the alternatives fairly, using commits is most of the time not more difficult than stash, and occasionally one or two extra commands. It's just not that hard to avoid stash, and there are significant benefits.


What's the way that one screws up with stash that doesn't happen with other approaches? I don't think I've seen stash accidents, though most of my colleagues don't seem to use stash much. If an attempt to pop conflicts, can't you just abort it?




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: