6 ms·
I think the most powerful tool for fixing mistakes is "git reflog". It doesn't fix everything, but it works very well as long as you view git with the right men
by alangpierce 8y ago
I think the most powerful tool for fixing mistakes is "git reflog". It doesn't fix everything, but it works very well as long as you view git with the right mental model: a git repo is an ever-growing tree of immutable commits, with branches and tags pointing to the most interesting ones. As long as code has ever made it into that tree (by being in any commit at any time), it's recoverable, and reflog lets you trace your steps back to any point in the past on that tree. Supposedly-destructive operations like amend and rebase actually just build the tree at a different point and move branches to other places in the tree, but (pretty much) nothing in the tree is ever destroyed.
For the actually-destructive git commands like checkout and reset, another tool that I'd highly recommend is a "local history" feature in your editor. JetBrains IDEs do this by default, and other editors have plugins for it. It automatically records changes as you make them so you can go back to previous versions of any file. Usually git is enough to save me, but I've also had plenty of times where I make some mistake outside of git commit history and am saved by digging through local history.
- magoon 8y agoLocal History in my IDE has saved me many times!
- Stratoscope 8y agoSmartGit has a brilliant implementation of the reflog. The Git command line reflog is just a list of hashes and messages. If you're not sure which of those commits is the one you want, it's a fairly laborious process to dig through them. What if you have several commits with the same message, as will happen if you've rebased or amended any commits? In SmartGit, you simply click the Recyclable Commits checkbox in the Log view, and now everything in the reflog shows up in the log tree, just like any other commit. You can see immediately the parent of each reflog commit, and to see what you changed, just click one of them as you would any other commit in the log. SmartGit shows the differences immediately. Same thing for stashes. After all, stashes are really just commits by another name. Click the Stashes checkbox and they show up in the log too. SmartGit is full of features like this where something cumbersome on the command line is straightforward and easy. I've used it for years and recommend it highly. https://www.syntevo.com/smartgit/ https://www.syntevo.com/smartgit/
- Filligree 8y agoIt's also commerical, expensive software. I agree that it sounds useful, but are there any equivalent open source solutions?
- Stratoscope 8y agoIt's only commercial software if you use it for commercial purposes. They have a pretty liberal non-commercial license as well. SmartGit is free to use for any of these purposes: * to actively work on open-source projects, * for learning or teaching on a public academic institution, * in the spare time to manage projects where you don't get financial compensation for (hobby usage), * by public charitable organizations primarily targeting philanthropy, health research, education or social well-being. (Wording is from their license, English is not their first language.) https://www.syntevo.com/documents/smartgit-license.html https://www.syntevo.com/documents/smartgit-license.html For open source alternatives, a few people I've worked with like SourceTree. I don't think it has the integrated reflog though. I'd be curious about other recommendations too.
- X-Istence 8y agoI tend to work on both Open Source and Commercial software. The cost of context switching between different tools because of it's licensing makes it a non-starter to use one for open source and the other for commercial work. Granted, the cost of a tool is minuscule compared to the potential gains from speed of development, and any corporation that balks at paying for tools for their developers won't be in business very long, I still find myself penny pinching and using free and or open source tools, even if inferior or lacking in just one or two bits of functionality.
- TylerE 8y ago$99 is expensive? That’s, like, a half hour of my time
- andybak 8y agoNot everyone is on your hourly rate. Hardly anyone is on your hourly rate...
- jolmg 8y ago> For the actually-destructive git commands like checkout and reset, another tool that I'd highly recommend is a "local history" feature in your editor. Amen. Both vim and emacs do this by default, too. They keep all changes under a tree, so you can even undo your undos. Another thing that's saved me from destructive changes is the terminal scrollback buffer, which typically represents a timeline of my work. I have a habit of looking at `git diff` frequently. If I lose any of those because of an accidental `y` in `git checkout -p`, I can just execute `git apply` copy the hunks that I want (with the initial file diff header) and paste them in the same terminal, then Ctrl-D to finish.
- Filligree 8y agoI believe you need the undo-tree package for Emacs to do that. :)
- jolmg 8y agoundo-tree displays it nicely, but you can still navigate it on stock Emacs with C-/ alone. You can insert "foo", undo the insert with C-/, insert "bar", undo the insert with C-/, and undo the undo with C-/ to get back to "foo". This is also the case with vim. There is the gundo plugin to display a nice tree to navigate, but you can navigate it on stock vim with g- and g+. Emacs C-/ is actually equivalent to vim's g- and not the u command. EDIT: I wish emacs had something like vim's g+ to move forward in that history. If I wanted to move back to "bar" after the undos that I did, I'd have to undo the undo of the undo with C-/, and undo the undo of the insert with C-/. Then, if I wanted to get back to "foo" again, I'd have to undo the undo of the undo of the insert with C-/, and then undo the undo of the undo of the undo with C-/. This can get confusing quickly without the visual display of the tree, but it's just a matter of hitting C-/ enough times to get to where I wanted to be. EDIT 2: Now that I think about it, C-/ is not equivalent to g-, but it's the closest thing. It's just different models of undo that avoid any loss of state. While vim's model is an actual tree and undos are movements in it, emacs's is a ring and undos are inserted changes at the end of the ring. In vim you can be at any point of the tree, but in emacs you're always at the end.
- Boulth 8y ago> As long as code has ever made it into that tree (by being in any commit at any time), it's recoverable, and reflog lets you trace your steps back to any point in the past on that tree. Actually it's enough for the file to hit index (staging area) to be recoverable.
- u801e 8y agoTrue, but finding the right sha1 is a bit more difficult in that case (given that blobs and trees don't have much metadata associated with them when compared to commits and annotated tags).
- jolmg 8y agoDo you mean it as recovering it while it's still in the index, or is it possible to add a file to the index, remove it from the index, let days of commits pass and still recover it? If the latter, how do you do that?
- Boulth 8y agoOnce you add it to index it's in .git/objects. You can find it using `find` with modification date parameter. The name will be a hash but you can look at the contents. (there will also be a tree object with file names).
- eslaught 8y agoI would recommend never using git checkout to clear local changes, and instead recommend either git stash or git stash -p depending on whether you want to save the whole work tree or just part of it. The stash subcommand internally creates commits for the stashed content, so you can probably also get to them via the reflog, though I haven't personally needed to do this.
- deleted 8y ago[deleted]
- RichardCA 8y agoIf I have local "dirty" state that I need to hold on to, I just hide it in a temp directory like this: mkdir temp echo '*' >temp/.gitignore Quick, dirty, effective. :)