1

I want to do exactly what Undo working copy modifications of one file in Git? is asking, and I want to do exactly what How to remove local (untracked) files from the current Git working tree is asking, but I want it in a single command that works regardless of the git status of the file. Does such a command exist?

  1. Is it staged? Don't care -- after this command, it looks like the latest commit.
  2. Is it not staged? Don't care -- after this command, it looks like the latest commit.
  3. Is it unstaged? Don't care -- after this command, it looks like the latest commit (i.e., delete the file since it's not a part of the last commit).

I don't want to think! Just... undo the changes. Does git have a single command that'll do all three? If not, is there a way to write a git alias that can safely do this on any file/dir?

Daniel Kaplan
  • 62,768
  • 50
  • 234
  • 356
  • only a specific directory, or just resetting the whole repository? – lucidbrot Aug 18 '21 at 21:50
  • I think you might be able to do `rm -rf mydirectory && git checkout HEAD -- mydirectory` , but I have definitely not considered all eventualities. (e.g. make sure you don't delete the `.git` directory like this) – lucidbrot Aug 18 '21 at 21:51
  • I think you can get 1 and 2 without a problem, but deleting files that aren't part of the repository probably not. There are specific commands that delete uncommitted files, because once they're deleted they can't be recovered (unlike pretty much everything else managed by git). – larsks Aug 18 '21 at 21:52
  • @lucidbrot only a specific directory or file. – Daniel Kaplan Aug 18 '21 at 21:52

1 Answers1

4
git reset -- path/to/it && git checkout -f -- path/to/it && git -C path/to/it clean -dfxq

and you can make that a git alias like git partial-full-wipe-reset if you want, hunt those up to make it.

A little collaborative exploration of some still-nominally-experimental commands, see the comments, produces this:

git restore -WS path/to/it; git -C path/to/it clean -dfxq

because git restore -S is an index reset, adding W makes it the desired combined reset-and-checkout. You could further reduce it with

rm -rf path/to/it; git restore -WS -- path/to/it 

but there are some unusual submodule setups that would interact very badly with (like, that's the original submodule for the entire project, it was first git submodule added from right there so the original repository's still in place).

jthill
  • 55,082
  • 5
  • 77
  • 137
  • " hunt those up"? – Daniel Kaplan Aug 18 '21 at 22:39
  • [git aliases](https://www.google.com/search?q=git+aliases) – jthill Aug 18 '21 at 22:56
  • There are shorter ways (`rm -rf path/to/it && git checkout -- path/to/it` for instance) but this leaves the file dates untouched if possible, so this is the winner for a generic recipe. :-) – torek Aug 19 '21 at 03:08
  • 1
    @torek that doesn't do the reset though. Mr. Kaplan wants "looks like the latest commit." – jthill Aug 19 '21 at 03:19
  • @jthill oops, yes, `git checkout HEAD -- ...`. – torek Aug 19 '21 at 03:22
  • Sure, but the `rm` would have removed them already. Am I missing something? Hm, also: `git restore` by default runs in non-overlay mode so it might be convinced to remove files here, and in current Git you can make `git checkout` run in non-overlay mode too. I'd have to experiment to see if that can be made to do the job... – torek Aug 19 '21 at 09:53
  • @torek Ah: just `git restore -WS t` does it. There it is. Checkout with a path adds new files but won't delete existing ones, you have to reset for that., but restore -S apparently does the full reset, and `git restore -WS t` carries the deletion forward. – jthill Aug 19 '21 at 13:18
  • @torek: to be explicit, `>t/foo; git add t; rm -rf t; git checkout @ -- t` leaves the `t/foo` index entry. I like restore's `--no-overlay` default just because it's a handy way of doing this sequence. – jthill Aug 19 '21 at 13:53