3

Context:

I want to run rubocop in a git pre-commit hook, but I assuming I have a stashed change that would cause it to complain, and an unstashed change that somehow fixes this, the offending change would slip by rubocop.

My solution so far:

Before running rubocop, run git stash --keep-index -u to stash all unstaged changes before running rubocop

The problem:

After running rubocop, git stash pop restores the working tree to its previous state, but stages all those changes (which were previously unstaged)

My question:

Is there an option to pop the stash without automatically staging any of the popped changes?

or

Is there some other way to run a program on the project as it would be committed, instead of the working tree with possible unstaged changes?


To reproduce the situation:

# Set up a dummy repo git init echo foo > file git add foo && git commit -m "Initial" # Make a change and stage it echo bar >> file git add file # Make another change and *don't* stage it echo baz >> file # This is what I later want to restore: git status && git diff && git diff --cached # Stash only unstaged changes (and ignored / untracked files) git stash --keep-index -u # So far everything is as it should be git status && git diff && git diff --cached # Run whatever script on the code rubocop . # This is where things go wrong though: git stash pop # Both changes are now staged to be committed đź’˘ git status && git diff && git diff --cached 
3
  • @RomainValeri A typo indeed! Fixed it, thanks for letting me know :D Commented Sep 11, 2020 at 8:45
  • Writing a good pre-commit script is harder than one might think, because of the fact that Git commits from the index. Or rather, from an index, which may or may not be the index (git commit --only vs git commit --include). Using git stash --keep-index doesn't really get you where you want in all cases. I haven't actually gone and tested this method, but I think the "right" way to test a proposed commit is to use git checkout-index to copy the proposed commit to a separate testing area, test it there, and use that result (and never try to update index or work-tree locally). Commented Sep 11, 2020 at 8:53
  • If you're determined to keep working with git stash, though, remember to use git stash pop --index at the end, so as to keep the distinction between index copy and work-tree copy. Note that you'll have to reset the work-tree first. Commented Sep 11, 2020 at 8:54

1 Answer 1

2

Is there an option to pop the stash without automatically staging any of the popped changes?

Not an option, no, but you can get that effect yourself with

index=`git write-tree` git stash pop git read-tree $index 
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot, the git write-tree thing was exactly the hint I needed to make it work :D

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.