5 ms·
Simple question: why is there no git undo command shipped in box? There is absolutely no technical barrier to shipping such a command.
by howinteresting 3y ago
Simple question: why is there no git undo command shipped in box? There is absolutely no technical barrier to shipping such a command.
- paulddraper 3y agoLike, git revert? Or git reset?
- hinoki 3y agogit reflog? All of those need you to know what you’re doing and what exactly you want to undo
- nordsieck 3y agoIt would be a wrapper: something like: * git branch hidden current * git do-the-command-here * if we call git undo, checkout the hidden branch, otherwise delete it In practice, I think a lot of people call `git lg` often enough that they can just git reset --hard to a recent commit hash, or they manually create a just-in-case branch if they're going to do something risky/dangerous.
- howinteresting 3y agoLook at the last repository-altering operation you ran and reverse the effects of it. Add a --dry-run to see what it would do, and print out the command it runs as a way to teach people more advanced things about Git. Microsoft Word has undo. Git can as well.
- jsunderland323 3y agoDo you mean literally deleting your last commit? That would break a lot of the guarantees gained from the append only graph that git exploits for nearly everything it does. I think undo is too ambiguous in the context of vcs that it would be risky to introduce as a part of the cli api. What would you expect undo to do?
- masklinn 3y agogit reset —hard HEAD~1 It is already part of the CLI API. Or it could use the ref log (possibly augmented) as a literal undo log, and follow that. > That would break a lot of the guarantees gained from the append only graph that git exploits for nearly everything it does. The graph is really not append-only.
- wtallis 3y ago> The graph is really not append-only. The commit graph is effectively append-only, but the named pointers into that graph can be reassigned at will, which means some commits can become (more or less) unreachable and eligible for garbage collection.
- masklinn 3y ago> The commit graph is effectively append-only, but […] some commits can become (more or less) unreachable and eligible for garbage collection. Sound to me like the commit graph is not append-only.
- maleldil 3y ago> The graph is really not append-only. Yes, it is. You can't change a commit: you have to create a new one, and create copies of any child commits, which are also different commits. This generates a different graph. What changes are things like tags, branches and HEAD, but they're just pointers, not part of the graph itself.
- masklinn 3y agoMate go @ the GP they’re the ones who asserted a git undo would break assumptions. > Yes, it is. You can't change a commit You can remove commits from the graph. That’s not append only in my book.
- howinteresting 3y agoNo, I mean undoing your last action performed with git. Can be a commit, an amend, a reset. whatever.
- lloeki 3y ago> why is there no git undo command shipped in box? There is absolutely no technical barrier to shipping such a command. To undo something you gotta know what thing-that-you-did to undo in the first place. This is often achieved using the command design pattern, but git does not record commands, nor has such a concept. It only has state. Let's imagine it does record commands, what should a purported magical "undo" right after each one of these commands? - git branch topic - git branch -f topic cafebead - git checkout topic - git checkout cafebead - git checkout -- file - git commit # detached - git commit # on branch - git commit --amend - git reset HEAD^ - git reset --hard HEAD^ - git add foo - git rm foo - git rm --cached bar - git merge a b c # merge succeeds - git merge a b c # merge fails - git merge a b c # merge fails, resolve conflicts, add, continue - git merge --abort - git cherry-pick - git cherry-pick --abort - git rebase main - git rebase --onto main cafebead^ topic - git rebase -i # pick, reword, drop commits, one fails - git rebase -i # pick, reword, drop commits, one fails, fix, add, continue - git rebase --abort - git stash - git fetch - git pull You could come up with answers to that, but then, they would make sense only with one use case of what you intended to do with each command. To cater for that you'd start to need "git undo --this-way" or "--that-way". Any command that cannot be undone would break undo. Any external tool would need to operate using only commands, or it would break undo. Any external too or script extending git by chaining commands would need to implement new commands with undo for it not to break undo (otherwise "git undo" would only undo the last one). Also, consider that there may be files untracked in the tree and tracked in other branches, become tracked midway through a merge or rebase and whatnot. It becomes stupendously complex stupendously fast. If "git undo" were made for beginner users to make it more approachable, then it would fail as soon as the user faced a non-undoable situation and not understand why ("this undo is stupid!"). If "git undo" were made for advanced users to make it more convenient, then it would fail as soon as the user used advanced tools or scripts breaking undo. What git chose to do is to be the simplest possible tool: it's a DAG made out of commits that can be labeled, and its commands operate on the DAG and labels (with a staging area so that commit creation is transactional). Commits are not removed until they're GC'd and "undoing" is moving back labels to be pointing to commits as they were before, so not having "git undo" is not even dangerous. To make "git undo" robust, git would need to hide and/or change its core design + API + UI, which would make it not-git. I'd argue that part of the success of git is these "internals" (which are its actual interface) made it spectacularly easy to script, extend, compose, write alternative implementations of... The only way to implement "git undo" is to embrace the database-like design (stage manipulation with git add and git rm are preparing a transaction that gets committed with git commit) and explicitly start (git start / git begin, records current work tree + refs + index state) and end (git end, a.k.a discard recorded state) or rollback (git undo / git rollback, restore recorded state). BEGIN TRANSACTION git begin INSERT INTO ... echo >> foo && git add foo && git commit UPDATE ... WHERE git cherry-pick bar DELETE ... (SELECT ...) git rm baz && git commit COMMIT // or ROLLBACK git end # or git rollback Now you gave me some ideas... hold my beer...
- williamdclt 3y agoThere is absolutely a ton of technical barrier to shipping this. I don't know that much about internals, and I can imagine quite a few off the top of my head. For example: a number of operations are not reversible in the current git model because they're not tracked. We'd need git to start tracking uncommitted changes so that it can restore them on `undo`. That's a fundamental change to how git works and I doubt that the idea would be entertained
- masklinn 3y ago> For example: a number of operations are not reversible in the current git model because they're not tracked. We'd need git to start tracking uncommitted changes so that it can restore them on `undo`. No? If an operation is not reversible then it’s not undoable. That’s not abnormal. The opposite really.