
How to undo almost anything with Git - agonzalezro
https://github.com/blog/2019-how-to-undo-almost-anything-with-git
======
npongratz
I've used the following flow chart to help determine strategies to get myself
out of messes:

[http://justinhileman.info/article/git-
pretty/](http://justinhileman.info/article/git-pretty/)

Just another way of presenting similar information. No affiliation, just a
satisfied consumer of the info :)

~~~
mikekchar
Ha ha! I like the part of the flow where it goes: "Is anyone downstream?" ->
yes -> "Enough to form a lynch mob?" -> no -> "Do you hate them?" -> yes ->
"We're going to do an interactive rebase".

------
mmanfrin
My only real git crisis was when I accidentally `git push -f`ed what I thought
was my own branch, but actually the `develop` branch. On a monday. After a
weekend where about a hundred commits had been cherry picked and merged in to
develop by a dev not in the office. None of my coworkers had recent versions
of develop.

The thing that ended up saving me was our CI -- we autodeployed passing builds
to our staging env; so we were able to ssh in and `git push -f` back from
staging to our repo.

~~~
chjj
My most recent major git crisis wasn't reversable by git.

A little while ago, I accidentally did a `git clean -xdf` on my home directory
(wrong tmux tab). I index my home directory: just the most important config
files, among other notes and text files. That `git clean` call wiped half my
home directory before I realized what was happening and frantically tried to
^C and ^\ it. I had to find other ways to recover my files.

The deleted files weren't essentially important, which is why I didn't back
them up frequently or index them, but they were moderately important. That was
a bad day.

I realize it's probably better to dump everything in ~/.config and index that
instead, while maintaining symlinks in ~/. It was just the way I had it set
up.

~~~
leni536
I suggest to use GNU stow for managing config files and keep your repo in a
separate directory.

------
johnnymonster
This does not cover the only scenario which I was hoping it would. I
accidentally pushed my api key/password to github and I want to "undo" that
push and completely remove the history locally and on an origin? This is so
obscure across many different outlets. And go ahead, flame me for pushing my
password/api key to github, but all of you know you have done this at least
once in your life!

~~~
akerl_
[https://help.github.com/articles/remove-sensitive-
data/](https://help.github.com/articles/remove-sensitive-data/)

That said, as the article points out, you need to consider them compromised
once they've been pushed and rotate the creds.

~~~
pimlottc
To add to this, this is not just good paranoid practice. Don't just think
you're safe because you fixed it 5 minutes later and probably no one noticed.
There are sites that monitor the global github commit feed looking for things
like AWS credentials and SSH keys. If it's been pushed to a public github repo
for even a moment, it's been grabbed.

~~~
scott_karana
Even slightly more obscure things, like the config file for Sublime SFTP
(`sftp-config.json`) have been personally observed as a target of crawling.

------
js2
Was this taken from
[https://news.ycombinator.com/item?id=9661349](https://news.ycombinator.com/item?id=9661349)
or is it just a coincidence?

------
forrestthewoods
I'm so glad I use Perforce. Yeah branches are a bit cumbersome. But it's idiot
proof. There is literally no way for any artist to cause irreversible harm.
They can't even do harm that isn't easy to fix with a few clicks in an easy to
use, easy to understand, easy to discover GUI.

I suppose one of the key features of Git is the ability to rewrite history. It
makes a lot of sense in the context of an open source project pulling in
changes from the wild. For most of us such utilities aren't just useless
they're actively harmful.

Never leave me P4. Please God never leave me.

~~~
erikb
I'm a huge git fan but I have to agree. At least some of the VCSs out there
should be non self-destructive. Git is really bad if not all users of a repo
take the time to learn to use it efficiently.

~~~
learnstats2
> Git is really bad if not all users of a repo take the time to learn to use
> it efficiently.

The "if" clause here happens rarely enough that I can quote just the first
four words of the sentence: "Git is really bad."

There are 2000 words here on how to undo.

~~~
erikb
Well, git should not be the default, but that doesn't make it a bad tool.
Think about different heads for screw drivers. Just because you have bought a
set and there is one you never or seldom use, doesn't mean it's a bad head.
The moment someone has a screw which needs that head suddenly all other heads
are useless and that's the best head you can have. Right?

(I'm not so sure what the right English word for "head" is, I hope it still
makes sense even if I use the wrong one)

Or another example. Cars are a highly specialised tools. Nobody is allowed to
use one if they haven't shown that they have learned to use it properly via
standardized exams. Maybe if a company uses a lot of git the mistake is that
they don't require people to learn it properly first, either by offering
courses or by filtering in the hiring process.

And since I've spent month learning it and now can use it even in potentially
destructive situations like "git rebase -i" I can tell you that for me it's
way more useful than SVN or CVS ever were.

------
thyrsus
Something I'm still working out....

I have a directory tree full of test data. As the project goes along, the test
data will evolve, and thus should go under revision control.

Testing needs to start with known files, so, hey!, git checkout test_data -
except that means my latest code revisions need to go into the test_data
branch even before they're tested :-(.

Then the tests make their changes to the data, which the tests check, and
which I then want to throw away. So: "git checkout test_data -f; git clean -f"
\-- except that cleans out the source code area as well as the test data area.

I'm thinking the test data should be separate repository. Is that a mistake?

[Edit] I've tried looking at stackoverflow.com, but searching for "git
testing" returned ~7000 articles, the first few hundred of which didn't look
relevant.

~~~
pjc50
Sounds like something that would be a lot easier to handle with "svn revert"..

~~~
lmm
Only if you're looking for excuses to prefer svn. You can do the exact same
thing you would with 'svn revert' with 'git checkout --'.

------
alphydan
until this happens: [http://renooble.tumblr.com/post/18845123629/git-funny-
scary-...](http://renooble.tumblr.com/post/18845123629/git-funny-scary-story)

------
crimsonalucard
as great as git is, I wish there was something more intuitive. Git is
definitely one of the more confusing tools out there.

~~~
VLM
I'm curious if you don't like the concepts of how it works or the UI or maybe
the workflow.

A workflow example would be doing a rebase after a push is almost universally
seen as naughty so why permit it without some kind of UI like --I-really-know-
what-i-am-doing=yes or something?

WRT the UI itself, I've read a couple people claiming the emacs magit package
is easier to use than the CLI itself, which would isolate the problem to the
GUI. I have not personally invested the time into magit and would find
comments on that theory by people who have experimented to be interesting.

[http://magit.vc/](http://magit.vc/)

~~~
zyxley
Git's CLI is just awful in a bunch of ways. There's a bunch of commands that
do two or more different things depending on how you use them, and whole piles
of cryptic and incomprehensible error messages.

Heck, the just the contrast between `git add <file>` and `git reset HEAD
<file>` is terrible.

~~~
mnarayan01
I wouldn't describe the CLI as "awful", though I hear your complaint.

Not sure where you're going with `add` versus `reset` though. `git rm --cached
${file}` would presumably do what you want with parallel syntax.

~~~
zyxley
The sane way to do it would be to have something like `git stage` and `git
unstage`, as distinct single-purpose commands.

~~~
mnarayan01
The first example at [https://git-scm.com/book/en/v2/Git-Basics-Git-
Aliases](https://git-scm.com/book/en/v2/Git-Basics-Git-Aliases) is literally
exactly what you want.

~~~
zyxley
"It's easy to make the CLI less bad, but the developers have never bothered to
do so themselves" is reinforcement of my complaint, not dismissal of it.

~~~
mnarayan01
Not trying to dismiss, just assist ;)

------
chx
Though I walk through the valley of the shadow of rebase, I will fear no evil:
for reflog are with me (sorry, couldn't resist)

------
daxelrod
See also
[http://sethrobertson.github.io/GitFixUm/fixup.html](http://sethrobertson.github.io/GitFixUm/fixup.html)
which has helped me immensely in the past.

------
nbouscal
This is pretty good, I had never seen autosquash before. Another rebase flag
that I find useful is --onto. For example, to rebase only the most recent N
commits of a branch onto master:

git rebase HEAD~N --onto master

------
chriscool
Instead of "git reset --hard stuff", I recommend "git reset --keep stuff" as
it will not delete uncommited files in the working directory.

~~~
jgraham
That is reasonable, depending on what you are trying to achieve,, but I think
the explanation you gave is a bit misleading. Neither --hard nor --keep affect
files that have never been comitted. The difference is that --keep aborts if
it would affect a file that is tracked, but has uncommitted changes.

------
ocdtrekkie
This is pretty useful for Git noobs like me.

------
jokoon
git checkout is what I want to do most of the time, but I always have been
confused with svn checkout, so I never could remember it.

------
vacri
One particularly tricky thing that this page doesn't mention is removing
binary blobs (or any file) from the history. Someone committed tens of
megabytes of binary stuff to one of our repos. A later commit 'fixed' this by
removing them. But those binary blobs are still there, because it's a
historical commit, meaning every time you clone the repo (or similar) you get
huge amounts of crap.

Maybe --squash will fix it? Something to look at, I guess.

~~~
Skinney
As far as I know, you need to use rebase --interactive and delete the
commit(s) that introduced the blobs. This will, however, create a new tree
which can be painful for everyone involved.

