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

Very cool. The idea which I liked most, is the ability to switch between branches, even though you still have uncommitted changes. With git, I'm forced to either make an extraneous commit, just to enable branch switching, or stash all my changes into a stack which I may later forget all about. Both of the solutions above are really cumbersome and prevent easy context switching.

The only feature I noticed missing, is the ability to stash changes. I use this most often to move changes from one branch to another branch, without cluttering history with an extraneous commit. How would this work on gitless?




> With git, I'm forced to either make an extraneous commit...

You only need to commit or stash if there are conflicts, and many time there aren't, so you can first try to switch branches without stashing.

> The only feature I noticed missing, is the ability to stash changes. I use this most often to move changes from one branch to another branch

I started a big ol thread on stash yesterday, but there are a bunch of safer alternatives to stash. You never have to clutter history, you can always move things around and still keep it clean. Problem with stash is it circumvents git's normal systems, so it's a little dangerous (which the stash man page mentions.)

https://news.ycombinator.com/item?id=12612630

If there are conflicts, you could do this instead:

  $ git checkout -b work
  $ git commit -am "WIP"
  $ git checkout another_branch
  $ git cherry-pick work
  $ git branch -D work
Exact same effect as stash with no clutter left over in the history, and much safer. The advantage here is your changes are put multiple places and referenced by git, so if anything ever goes wrong it's in the recent reflog. With stash, if you have problems, your only option is to use fsck.

Given that the whole point of gitless is to avoid super confusing and intimidating commands like fsck, especially for beginners, it makes sense to me they chose not to include stash.


The whole advantage of stash, the way I see it, is that you don't need to type out a whole bunch of commands to stick something into another branch and deal with remembering where you put it and what you called it and so on.

I started out using secondary branches since that was the intuitive way of doing things, and I had issues with stash before, but after a while I went back to using stash again because it's just so much faster to stash my config differences, do all the necessary merges or pulls or switches, and then just stash pop. A large part of the advantage is that stash is a bit orthogonal to the usual workflow, so it goes in a specially defined place in my brain vs being yet another branch, especially if I already have work/dev/backup branches for other purposes.

I agree that I wouldn't recommend using the stash to beginners, though, it does really odd things at times if you are not clean with it. First time I used stash, I lost all my code and nobody could figure out how to get it back. :P

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.


Stash for you is fine, you obviously know what you're doing, and you use it carefully. And if you're comfortable with fsck, you really don't have to worry.

OTOH, the alternative workflows are really not that hard, it's really not a ton of commands compared to using stash. The single most common use case I've heard so far is switching branches, and for that you can skip stash the majority of the time, many people don't seem to know that.

Your example was stash during a pull, if you do that, your workflow is:

  $ git stash
  $ git pull
  $ git stash pop
The alternative is:

  $ git commit -am "WIP"
  $ git pull
  $ git reset --soft
Not only is it the same number of commands, and safer, it's also less to remember because you don't have to use the stash subsystem at all. Commit, pull, and reset are commands you have to know regardless, you can't avoid them. Stash isn't one you have to know to use git. Stash is adding to the things you have to remember, or taking up space in your head that could be used to learn flexible ways of making temporary commits & branches.


I don't know if I really know what I'm doing... feel free to correct me if something feels off.

I'm not following your alternative. Did you mean "git pull --rebase"? Because this will result in there being a WIP commit in the middle. I try to pretty much never do pulls like this, I'm in the "rebase everything to smithereens camp".

I don't want accidental merges. I do not want to have to rebase because I got a commit in the middle and it's named funny. And what I also don't want is having to deal with merge conflicts in the rebase or merge in case incoming changes don't like the changes in the WIP commit.

It's a lot cleaner to just not have the stuff in there at all, pull, and put it back on top. (like the stack that stash presents)

Yes, I am that lazy.

This is not really the way I used to do it. An example is just an example, the situations are many. Maybe I want to pull. Maybe I need to rebase my stuff. Maybe I need to switch to another branch to show something to a coworker.

I'd have to make a special branch, commit to it, and then grab the commit hash and cherry-pick that whenever I needed it. Because I would need it in all sorts of different situations. So part of the issue was keeping track of the hash. But the bigger problem was how much work I'd needed to do if I ever needed to bring those changes up to speed again. With stash, I get a merge conflict and I resolve it, and that's my new stash again, I don't even have to do anything. With a commit or cherry-pick, I have to undo it, fix it, commit it, and now manage a new hash.

I find stash easier to manage in my head specifically because it's a separate thing on the side so it doesn't get mixed up with all my other branching. It's very little headspace at this point, and mostly a decision tree in the form of:

- is the staging area empty and I want to start doing work? stash pop;

- is the staging area currently holding my stash changes and I want to do some things with git? stash.


> Did you mean "git pull --rebase"?

Yes.

> Because this will result in there being a WIP commit in the middle

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

Doing a commit+pull+reset will always work exactly as easily as stashing.

It's no less clean to commit & later reset than it is to stash & later pop. The difference is that if you commit you have a bigger safety net than if you stash.

I totally understand that stash feels easier, a lot of people agree with you. But I don't think it's true once you dig down and learn how to not use stash. And stash is more dangerous when something unexpected happens.


> 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?


I wish git would deprecate stash and replace it with something like this, that doesn't have any magic and just uses the existing branch system.

It would generate a new temp branch every time using a counter system, e.g. "stash1" "stash2", so all the temp branches effectively form a stack. The stash popping behaviour can still be supported this way (popping would cherry-pick and delete the highest numbered branch).

It would be easy enough to script as a side project too.


Yeah, exactly. I don't understand why stash wasn't done this way. They didn't have to circumvent the reflog, it was a choice, and one that bites a lot of people.


> You only need to commit or stash if there are conflicts

Unless you're wanting to take a look at the other branch clean, then you have to stash or do the extraneous commit. Most of the time I change branches to check someone else's work, or compare something that isn't working to develop/master. The stash/commit dance is a regular annoyance for me


This is true, you have to stash or commit, if you want to go to another clean branch.

But, your code is going to be committed & rebased later in your own branch anyway, right? If you commit some partial changes & later come back, make some more commits, and rebase/squash before pushing, you haven't done anything extra you wouldn't have done anyway.

By stashing, going away, then coming back, popping, working, committing, rebasing & pushing, you've added extra steps to the general case by involving stash, and you've added an extra failure point. If you commit instead, your changes are already there when you come back, and they stay associated with your branch while you're gone. It's harder to forget what you were doing, and it's much harder to lose your work accidentally if you commit.

I've witnessed the exact scenario you describe go bad several times when people go code review or test someone else's code, and the forget what they were doing. Sometimes people will stash again while working in someone else's branch, making it hard to keep track of which stash is which. That can lead to accidentally dropping stashes, or to popping the wrong stash.

Try only using 'git commit -am "WIP"' as a git stash replacement for a while and see if it really is any harder than stashing. To uncommit a WIP commit (which is always optional -- you could wait until you rebase -i) just 'git reset --soft HEAD^'.


> I'm forced to either make an extraneous commit, just to enable branch switching

Which you can later squash via interactive rebase.


gitless gives each branch its own separate worktree (see `git worktree`), and saves/restores them when you switch branches.

Also, there's no harm in creating "temp" commits. If you are having multiple branches, you probably want to give your current state a name - which is what a "temp" commit is.


Just use the normal git fallback command


me nor my web search engine never heard of it


Perhaps m3kw9 means that if there's something that you can't do in Gitless, you can fall back to the Git way of doing it, since both use the Git plumbing.


> Both of the solutions above are really cumbersome and prevent easy context switching.

Too frequent context switching might actually be perjudicial for your productivity and health, while increasing stress levels. So git not making it trivial might not be a bad thing, in my opinion.


I don't think perjudicial is a word.


Just a misspelling of prejudicial


you are wrong


It seems to be a word in Spanish. It isn't a word in English.


prejudicial is absolutely a word in English. look it up


But "perjudicial" is a word in Spanish, meaning "harmful", "detrimental". I think that was the meaning intended.


Thank you.




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

Search: