-1

I broke my own rule of having more than one item in my git stash stack, and I git stash poped two of them instead of one.

That means I had two sets of changes, with no conflicts, now sat as untracked changes that I can't separate easily1.

So is there a way to make stash pop/apply interactive, and check I have no tracked or untracked changes before continuing?


1 Had there been conflicts I could have just use reset as in Actually undo git stash pop

AncientSwordRage
  • 7,086
  • 19
  • 90
  • 173
  • Someone said me a good advice, run `git status` before every single git command which has an effect on your repository. – Morteza Mar 26 '19 at 19:19
  • @MortezaZiaeemehr the mistake actually happened as I thought the previous command was `npm run test, and ended up popping twice. Thanks for the advice though – AncientSwordRage Mar 26 '19 at 19:23
  • 1
    I don't understand why people are downvoting this. It's a clear question about one of the cases where a git command cannot be easily undone. – Soulman Oct 22 '19 at 09:45

1 Answers1

3

You can create an alias for git stash pop or apply that checks for differences from HEAD.

[alias]
    pop = !"f() { { git diff-index --quiet HEAD && git stash pop \"$@\"; } || echo \"Can't pop, you have local changes\"; }; f "
    apply = !"f() { { git diff-index --quiet HEAD && git stash apply \"$@\"; } || echo "Can't apply, you have local changes"; }; f"

Prefixing with !, and wraping them in a function call f() { ... }; f ", allows passing arguments to git stash pop and git stash apply.

The command git diff-index --quiet HEAD will return 0 or 1 depending on whether there are local changes, then the && and || shortcuts will either continue with the git stash pop/apply, or output an error message.

Wrapping the first part, which uses the && shortcut, in braces (so it's { a && b; } || c ) prevents the error message which uses the || shortcut firing when the pop or apply fails.

Then you can use git pop to safely run git stash pop without interfering with other changes.

AncientSwordRage
  • 7,086
  • 19
  • 90
  • 173
  • 1
    As much as I don't like a setting where you idiotproof your environment in order to allow yourself consequence-free careless behaviour (pop/apply on a dirty tree) which could come bite you back one day when you switch to another environment without your aliases, ....I must admit this is clever and seems to work well. Well done. – Romain Valeri Mar 26 '19 at 14:28
  • @RomainValeri I don't like it either, but I consider git stash to both be too useful and too dangerous not to make it easier to use. Also bear in mind that `git pop` !== `git stash pop`, hopefully avoiding issues when I change environment – AncientSwordRage Mar 26 '19 at 14:29
  • You might want to tweak these slightly to pass arguments as well, so that you can `git pop --index` if you intended that. – torek Mar 26 '19 at 16:07
  • @torek you mean make it run a bash function or some other magic? – AncientSwordRage Mar 26 '19 at 16:14
  • 1
    @Pureferret: I'd define and then use a shell function just for sanity (`pop = !'f() { git ... ;}; f'`), if doing this. The whole thing is a little painful, so be sure you keep anything you have working before you head down this path. :-) – torek Mar 26 '19 at 16:57
  • 1
    Just a note that the `&&` and `||` in this case can have a weird effect if the first command succeeds and the second fails—it will print your error message. Typically `{ a && b } || c` works though. – D. Ben Knoble Mar 26 '19 at 17:08
  • @torek I've got it using a shell function now – AncientSwordRage Mar 27 '19 at 11:38
  • @D.BenKnoble just noticed that, I had to add a `;` in but it works – AncientSwordRage Mar 27 '19 at 11:39