DEV Community

Cover image for 3 ways to time travel in Git to undo destructive mistakes

3 ways to time travel in Git to undo destructive mistakes

Zak Laughton on February 27, 2020

Raise your hand if you can relate: // Detect dark theme var iframe = document.getElementById('tweet-1232412585397571584-502'); if (docume...
Collapse
 
slavius profile image
Slavius • Edited

Please note that you would only be able to achieve all this if your git repo was not garbage cleaned (yes, git has its own Garbage Collector).

There is an optional git config variable called gc.reflogExpireUnreachable that defaults to 30 days that clears all unreachable reflogs (not pointing to/from any live reflogs - a.k.a. lost commits).

Git garbage collection is run automatically on several frequently used commands:

  • git pull
  • git merge
  • git rebase
  • git commit

To prevent running automatic GC on your git repos run:
git config --global gc.auto 0

Similarly you could set to never expire reflog entries which would make your git repo to grow much larger than usually:
git config --global gc.pruneExpire never
git config --global gc.reflogExpire never

Collapse
 
zaklaughton profile image
Zak Laughton • Edited

Thanks for pointing this out! These tools are best used for resets to a recent state (within a few days at the most).

From my understanding, the default expiration is 90 days, but the impact is the same: if you have really old changes that you might want to use later, these should probably be reliably saved in a commit somewhere.

If you know ahead of time you want a reliable long-lasting backup of your branch state, you can create a backup branch before making changes.

git checkout my-new-branch
git branch my-new-branch-backup
# now reset, rebase, or otherwise destroy my-new-branch
# checkout my-new-branch-backup later to restore
Collapse
 
slavius profile image
Slavius

The thing is some tools enable/update/run git GC automatically (and sometimes even without you knowing). That might kill your whole reflog history and any attempts to restore... :(

Collapse
 
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan

Good to know!

Collapse
 
aleksandrhovhannisyan profile image
Aleksandr Hovhannisyan

Came here thinking this was gonna cover generic things I already knew, but nope! I actually learned something :) That last one blew my mind:

git reset --hard HEAD@{5.minutes.ago}

I'll have to keep this in mind!

Collapse
 
michelemauro profile image
michelemauro

Or you could just use a sane SCM system, like Mercurial that, by design, does not destroy history so easily: it is impossible in hg to remotely damage a shared repository πŸ€·β€β™‚οΈ

Collapse
 
brownio profile image
Antonio Djigo

Git Bisect is a really powerful tool too when you don't really know when something started to fail.

Collapse
 
jannikwempe profile image
Jannik Wempe

Exactly the same here! Awesome article. Thanks for teaching me something new πŸ˜„

Collapse
 
chathula profile image
Chathula Sampath

Great writeup. Learned new things that i never thought 😍😍 love the time traveling 😍

Collapse
 
leewarrickjr profile image
Lee Warrick

Great article! Well written and humorous, with great examples.

... Could you do one on how to rebase and squash commits?

Collapse
 
zaklaughton profile image
Zak Laughton

Glad you liked it! Rebasing and squashing is definitely on my list of things I'd like write about. Thanks for the request, and stay tuned...