4 ms·
I understand the line of thinking, but if you are doing "git reset --hard" you are saying "put the working tree (e.g. files) back the way they are in latest com
by fargle 4y ago
I understand the line of thinking, but if you are doing "git reset --hard" you are saying "put the working tree (e.g. files) back the way they are in latest commit".
So if there were no files or they were empty? Well, that's what you get.
Git is tricky and has a complex and oft panned command-line UI. This is not surprising either, widely known. I like it and get along with it fine; not everybody does.
But certainly you should not be running commands like `git reset` or `rm -fr <anything>` unless you really know what you are doing.
Surprising behavior is interesting if it's based on a good working knowledge of git and still a surprise. Being surprised that a keg of gunpowder blows up when set afire, but you just did not expect it to actually do that, is not as interesting.
- kazinator 4y agoThere is no "latest commit" in that example; one has not been made in that repo at all. The only prior state when the file didn't exist was before git was initialized. At no point did I make any edits to the file after creating it. Git invented that prior state by equating the addition of a file to the index to an operation which creates a file where there was no file before. I.e. git is pretending that the file originated in git's index object, which owns it. This is a good assumption for commits. When we check out to a commit where in which a file doesn't exist, leaving behind a commit in which it does, of course we want the file to disappear. If we throw away an uncommitted index in which a file exists, to return to a clean HEAD where it doesn't, it's a bad idea to remove the file in that case, even though the index is commit-like in some respects. There will be cases where that causes an unwanted file to inconveniently exist. Those situations could be taken care of by a flag in the index which tracks a file's provenance: was the file added to the index from the outside by a "git add", or is the file in the index as a result of a git operation (from where that file could be obtained again).
- sebazzz 4y ago> There is no "latest commit" in that example; one has not been made in that repo at all. Consider that the first real commit is to a virtual commit with hash 0000000... that contains an empty tree. I seems perfectly logical to me. OP did a hard reset to that virtual commit 000000.
- kazinator 4y agoThat's another screwup in git. That commit does not behave like a commit. For instance, you cannot do this: git reset HEAD^ -- file # stage a file removal from the commit or say you have made two commits and want to reorder them with interactive rebase git rebase -i HEAD^^ # oops Whenever I start a new repo, I do this: git init git commit --allow-empty -m NIL to create a commit that actually serves as a "terminating nil" in the list since for unfathomable reasons, the 0 commit hash doesn't serve that purpose. You can't point at that 0 with HEAD^ to indicate "the point before this commit".
- fargle 4y agoYep, agree. I should have been more clear about the edge case of no prior commit. anytime you do a "reset --hard" files and changes in the working tree are likely to get deleted/reverted/etc. That's as consistent as it gets. You don't reset --hard unless you want that behavior.
- fargle 4y ago> The only prior state when the file didn't exist was before git was initialized. And I'd say the state of a repo with no commits is an empty tree, which is completely rational and consistent. It's what you get when you clone a repo with no commits, for example. If you `git reset --hard` to this state, that's what you get. The ironclad rule is ANYTIME you run `git reset --hard` you are going to reset the work tree and have the potential to remove files and lose uncommitted changes. That command exists for this reason and is quite useful for when you want to remove and throw away anything that might have changed. Although `git reset` and `git checkout` are overloaded in IMHO confusing ways, `git reset --hard` does exactly what it says it will - the other usages are the odd ones. Don't ever do `git reset --hard` if you have uncommitted changes (e.g. the repo is dirty). There's no special case for "before the first commit". Another way to untangle the two issues 1. prior to first commit / invented previous state and 2. git reset --hard eats your file is to note that `git reset --hard` would "eat" an indexed, but not committed, file in exactly the same way if you `reset --hard` to a prior commit when there are prior commits too. No difference. If you `git reset --hard` with uncommitted changes to an previously committed file, indexed or not, the changes are reverted too. It's the whole point to `reset --hard`.