15 ms·
Git Undo
- derefr 10y agoMost git command-lines are lengthy enough to give me time to consider them, so I don't often feel the need to "take back" a git invocation. What I do often screw up, though, is the (almost hypnotic) tapping of y/n when doing a `git {add, reset, checkout} -p` to prepare and clean up a commit. Ideally, with all of the -p commands, git wouldn't actually apply any of the changes I specified until it was about to quit (i.e. either when I advance past the end of the set of potentially-affected hunks, or I manually type 'q'), and then would prompt me for whether {set of operations I specified} is what I wanted to do. This would leave the -p operations the the flexibility to expose an 'u'ndo.
- arghimonmobile 10y agoYou'd probably really like Magit mode for Emacs then. What you're describing with interactive add becomes trivial since you can stage parts of the diff by selecting them in a region. I can hardly live without Magit these days. Bonus is that it even works on remote hosts via tramp. </emacs plug>
- throwanem 10y agoI can enthusiastically second this recommendation. If you use Emacs and Git, but have not yet tried Magit, you are missing out.
- roblabla 10y ago<vim plug>With the vim-gitgutter plugin installed, you can dynamically add/remove/undo hunks without even leaving the editor[0]. I use this instead of `git add -p` nowadays</vim plug> [0]: https://github.com/airblade/vim-gitgutter#getting-started https://github.com/airblade/vim-gitgutter#getting-started
- hacker42 10y ago<spacemacs plug />
- Tyr42 10y agoAs long as its not the last one, you can go back with `K` to the previous hunk. And forward with `J`. (The lowercase versions only go to hunks you decided to skip, but uppercase go to all, even ones you already chose an option for)
- dan00 10y agoNice idea! The only non intuitive thing might be, that calling e.g. 'git undo' twice doesn't undo the last two changes, but the first undos the last change and the second one undos the undo.
- m_mueller 10y agoCould it be improved to have undo filter out its own reflog entries and instead have a 'redo' to undo those?
- dan00 10y agoI don't think that 'git undo' can tell with certainty which entries in the reflog are from it. It would be a crude heuristic that's going to break.
- m_mueller 10y agoIs there maybe a way to annotate the commit message of HEAD without influencing the reflog?
- dan00 10y agoYou can't change the commit message of a commit without changing the commit, which in most cases is a bad idea, if you don't know pretty much exactly what your doing. Replacing one heuristic with another won't make this a stable operation. A lot of people had already the idea to encode relevant information inside of documentation and it was always a bad idea in the long run.
- m_mueller 10y agoI get that, I just wondered whether it's technically possible (with supported git operations, not hacking down at FS / byte level).
- 10y ago
- garaetjjte 10y agoIt should automatically skip reflogs created by undo itself, so git undo; git undo be equivalent to git undo 2, and for undoing undo there should be seperate git redo.
- ekzy 10y agoI agree with that. So you could undo step by step without thinking about the number to put next to your undo command. It seems a bit trickier to implement, though
- garaetjjte 10y agoOnly a bit of awk magic: ~/git-undo.awk: BEGIN { jmp = 0 } { match($2, "{([0-9]+)}", c); if (c[1] == jmp) { jmp++; if ($3 == "reset:") { match($6, "{([0-9]+)}", x); jmp += x[1]; } else i--; if (i == 0) { print jmp; exit; } } } git config --global alias.undo '!f() { git reset --hard $(git rev-parse --abbrev-ref HEAD)@{$(git reflog | awk -v i=${1-1} -f ~/git-undo.awk)}; }; f' Redo is also possible, but i don't have time now to do it.
- mnx 10y agoThis seems dangerous to get used to. I always thought the reflog was supposed to be last-resort. Isn't it?
- cjbprime 10y agoThat doesn't sound right. There's nothing secret or internal about the reflog. "reset --hard" is more of a last resort, but only because it wipes uncommitted changes.
- deleted 10y ago[deleted]
- amelius 10y agoWhy not just use a filesystem which supports snapshots? It would allow you to go back without even invoking git.
- charlesdenault 10y agoBecause a simple, but clever, alias that integrates with everyone's existing workflow is a lot easier?
- throwanem 10y agoWhy not just boil the ocean?
- Dylan16807 10y agoUsing a better filesystem isn't that hard. Sure, on windows you have to set it up as a network drive, but that's a few minutes of effort.
- dboreham 10y agoThat was called : ClearCase.
- dozzie 10y ago1. calculating differences 2. merging two or more different branches 3. transporting code (publishing it) 3a. accepting somebody else's patches 4. descriptions of history points 4a. pointers to parent code trees (especially with tree merges) 5. history traversals (bisecting, among the others) Not to mention that you need either administrative privileges for creating a snapshot or a special kind of filesystem that supports this for non-administrator. And sysadmin still needs to prepare such a filesystem for your $HOME.
- Dylan16807 10y agoWhat are you talking about? amelius is mentioning an alternative to the hacky "git undo", not an alternative to git. You put your git repo onto the filesystem. As far as administration, most devs will have elevated rights or can use FUSE or something. We could talk about needing administrative privileges to install git, too, but it's pretty far removed from the central topic.
- rjbwork 10y agoI freely admit to being an Hg fan, but that this stuff is accepted as common practice kinda blows my mind. What's so wrong with keeping an accurate picture of history that people do all kinds of manipulation to their history to keep from the VCS system from accurately reflecting history of development?
- _pmf_ 10y ago> What's so wrong with keeping an accurate picture of history that people do all kinds of manipulation to their history to keep from the VCS system from accurately reflecting history of development? What's wrong with organizing your source code in a single directory? Why do people insist on organizing them into subdirectories aud subsubdirectories instead of letting the main directory accurately reflect the size of the code base?
- mikekchar 10y agoIt's just a way of looking at it. Let's say I'm in charge of a project. You send me a patch. I commit the patch. What I want in my history is that I committed your patch. I really don't care what you did in your history to create that patch. But it's equally valid to consider all your commits important in my history as well. It just depends on what you want. Personally, I never rebase, but I can understand why some people like that feature.
- k__ 10y agoThat's what I find hard with contributing to OSS often. Many devs are happy with what you send them... as long if the history is right! And right seems totally random to me. Most are happy if you simply send them "one commit", but tell you to merge multiple commits before they accept it. Others say "lets split this or that" before they accept it. Then I have to go back and fiddle around with Git just to get my change landed...
- chriswarbo 10y agoThere seems to be a split among git users between those who think history should show what actually happened (i.e. it's left alone), and those who think history should tell a story about the changes (i.e. once you've finished something, turn it into a coherent set of commits like "stub out X", "add tests for X", "make first X test pass", etc.). I agree with you, that history should be left alone; mostly I think of the YAGNI argument that its futile to think that you have a better idea of what future developers want to see, compared to those future developers themselves. My repo histories are riddled with stuff like "finished X", "stubbed out Y", "fix typo in X", but at least nothing has been hidden from future devs who might be digging around for their purposes, regardless of whatever elegant story I might come up with.
- ricardobeat 10y agoWarrants a big warning that using `reset --hard` will irreversibly wipe out any uncommitted changes.
- Flimm 10y agoAlso doing `git checkout -- filename` will lose the changes to that file permanently. The only feature I miss from Bazaar was that it would create a backup file automatically for its equivalent command. I have actually created a bash function that overrides git to add this functionality (since there is no pre-checkout Git hook and Git doesn't allow you to create an alias named "checkout").
- sleepychu 10y agoCame here for this. git undo won't restore the changes wiped out by reset --hard? They aren't stored on the reflog?
- panic 10y agoIf it hasn't been committed, it won't be in the reflog. Working copies and stashed changes are especially vulnerable to being overwritten by accident. It would be great if git had a way to undo these operations too.
- 2T1Qka0rEiPr 10y agoI find reflog one of the neatest git features, and regularly use it to get out of jail / help cherry-pick across branches. This seems a bit magical, but I think there are some pretty neat lessons within for lots of users which still makes this a great read.
- Confiks 10y agoI always make sure to keep a `git log` in my terminal scrollback buffer, so I can easily `git reset --hard` back to some revision. And if that fails there's indeed always the reflog to fall back to.
- nihilisticape 10y agoThe alias is only useful in the simplest use case. Where you just want to undo the latest one change. Reusing undo to revert the undo is counterintuitive. If you want to know how many steps back you need to undo, you still need to check reflog. This means you're better of just resetting manually to the change you want.
- richardwhiuk 10y agoI worry about naming a function undo that doesn't necessarily undo what the user expects. Undo has a strong user expectation, and I'm not convinced this matches that.
- Mchl 10y agoGit already has `git branch` which doesn't in fact do any kind of branching but creates a label which follows commits when it's checked out.
- krupan 10y agoYou are absolutely right and I'm sorry to see you getting downvoted. See: http://bryan-murdock.blogspot.com/2013/06/git-branches-are-not-branches.html http://bryan-murdock.blogspot.com/2013/06/git-branches-are-n...
- phaemon 10y agoIt doesn't immediately make any kind of branch, but if you then create commits using both of the labels it will inevitably create a branch in the DAG so it's not terribly misnamed.
- nf05papsjfVbc 10y agoYou can look at it as a copy-on-write optimisation. It may not be so poorly named if you look at it that way.
- OJFord 10y agoThat's all a Git branch is though; so it makes perfect sense for the command `git branch` to do that.
- panic 10y agoGit also has 'git revert' which creates a new commit, 'git reset' which actually reverts (among other things), 'git checkout' which switches branches... the fact that all the other commands are confusing doesn't mean this new one has to be.
- 10y ago
- p4bl0 10y agoI have this alias in my ~/.gitconfig: cancel = reset --soft HEAD^ I don't want an alias to hard reset, it seems to dangerous and a good way to lose some work. However a soft reset like this allow me to cancel the last commit and add an omitted file, or remove one from the commit, or simply to correct the commit message easily.
- phaemon 10y agoActually, if that's all you want, you can do: git add <file> # or "git rm --cached <file>" to remove git commit --amend and it will replace with a new commit that has what you want. It's like a mini rebase -i
- p4bl0 10y agoTrue, but I prefer to be able to see my staged changes as a whole to be sure that I did everything as I wanted.
- deleted 10y ago[deleted]
- tempodox 10y agoYep, git gives you more than enough rope to hang yourself with.
- ChoHag 10y agoI have this. It's called cp(1).
- tempodox 10y agoGranted, you can shoot yourself in the foot with cp(1), but not nearly as much as git(1) lets you.
- panic 10y agoI wonder how much time and money has been wasted trying to operate Git's confusing UI. The repository format itself seems fine, but I'm surprised we're not all using a better frontend by now.
- oblio 10y agoIt's the "boil the oceans" problem (http://www.urbandictionary.com/define.php?term=%22boiling%20the%20ocean%22 http://www.urbandictionary.com/define.php?term=%22boiling%20...). Same thing that happens with vi, for example. You have a widely adopted tool with some real or perceived flaws. Everybody knows them and wants to fix them. But unless you somehow get mass adoption from the start, the project flounders because everyone will be pointing out that you can't install & use the new tool in restricted environments or on very old environments. So we're left with the lowest common denominator. At this point, to break the cycle, either the original developers come with the 2.0 interface and push it hard (which might cause backlash: https://xkcd.com/1172/ https://xkcd.com/1172/) or someone with a ton of pull and resources does it from outside (which could trigger a fork or other unpleasantness).
- blakeyrat 10y agoExcept we all knew how to write better UIs back in 2008 when Git was first written. It's not some brand-new research that only came to light a few years ago. We knew how to do usability tests in 2008. We knew what patterns worked and what didn't. We knew how to build discoverable software. Why the heck wasn't the UI improved back then, before the thing was even released? I mean, while your explanation is correct, it doesn't explain or excuse the pure incompetence of the original developers when it comes to usability issues. Their laziness or ignorance back then has confused and irritated thousands or millions of developers now, and continues to, and will continue to for the foreseeable future. Make sure the shit you're going to set in stone is good before you grab the chisel, guys. You're professional software developers, not clowns. Sorry for the rant.
- Cthulhu_ 10y agoOne can argue semantics whether you call it a UI or a CLI, but hey. There's a number of GUI clients out there that depending on your criteria could be considered better. They're usually not as powerful as the CLI client though, and if they are, features like accessing the reflog are hard to find and use. There's also a few alternative CLIs out there, I've just done a quick googling and came across http://www.saintsjd.com/2012/01/a-better-ui-for-git/ http://www.saintsjd.com/2012/01/a-better-ui-for-git/ and http://www.kennethreitz.org/essays/legit-the-sexy-git-cli http://www.kennethreitz.org/essays/legit-the-sexy-git-cli. Personally I prefer the CLI, it's the only tool that I can rely on to do what I tell it to do and to know what's happening. But it takes time and effort to get used to it.
- Grangar 10y agoWhat's wrong with git revert?
- supersan 10y agoI wish there was a Dropbox for developers where you never had to worry once about commits or history or tags. Maybe just a big green "Release" button and that's all there is to it. Surely it won't be ideal for writing the Linux operating system but for most of the cases that would be more than enough to get the job done, keep eveyone in sync and yes a lot less confusing allowing you to focus on things that really matter.
- jordanthoms 10y agoIf that's what you want, you can just use Dropbox itself to store code and use one of the several deployment tools which can pull code from it (e.g. cloudcannon). It quickly falls apart though as you don't have a proper history, reverts, or branching - it's OK for static sites but a disaster for anything more than that.
- lmm 10y agoSo what happens when two developers edit the same file, or make changes to different files that in combination break the system? You need commits, you need the ability to merge. If you don't want to force all commits to happen online and everyone to resolve conflicts immediately then you need branches. You want tags if you're going to have releases (otherwise how do you refer to them?). At that point you basically have git. All the complicated features were added because someone thought they needed them (there are certainly a few git features where I think that someone was wrong, but not many).
- tempodox 10y agoHave you ever tried subversion?
- deleted 10y ago[deleted]
- CyberShadow 10y agoBe careful with hard resets - they throw away working tree changes. Ironically, it's one of the few git operations you actually can't undo. (Usually I prefix such scripts with "git stash save" due to this.)
- dilap 10y agoif you're on a mac, the excellent & open-source GitUp graphical git client has undo built right in. it also makes it easy to slice-&-dice your commit graph.
- eliasdorneles 10y agoI've also wrote about undoing things in Git and other productivity tips here: http://eliasdorneles.github.io/2016/06/19/on-getting-productive-with-git.html http://eliasdorneles.github.io/2016/06/19/on-getting-product...
- forrestthewoods 10y agoEvery Git thread makes me so happy I use Perforce.
- tempodox 10y agoI find it wise to give git a command for reflogging. Flogging it only once would definitely not be enough by a long shot. It might afford the tortured git user some release, although it won't change git any.