(Translated by https://www.hiragana.jp/)
GitHub - jvns/git-oops
Skip to content

jvns/git-oops

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

EXPERIMENTAL SOFTWARE, MAY DO DESTRUCTIVE THINGS TO YOUR GIT REPOSITORY. PROBABLY DO NOT USE THIS ON A REPO YOU CARE ABOUT.

git oops

Have you ever made a mistake with git and wished you could just type git undo instead of having to remember a weird incantation? That's the idea behind git oops.

$ git rebase -i main
# do something bad here
$ git oops undo
# fixed!

The goal is to experiment and see if it's possible to build a standalone undo feature for git, in the style of the undo features in GitUp, jj, and git-branchless.

You can think of it as "version control for your version control" -- it takes snapshots of your repository and makes those into git commits that you can restore later to go back to a previous state.

This is really just a prototype -- I think the idea of a standalone undo feature for git is cool and I'm mostly putting this out there in case it can serve as inspiration for a better tool that actually works reliably. There's a long list of problems at the end of this README and it's not remotely ready for production use.

installation

  • Put the git-oops script into your PATH somewhere
  • Install pygit2 globally on your system
  • Run git oops init in a repository to install the hooks (danger! will overwrite your existing hooks!)
  • If you'd like, alias git undo to git oops undo

Now git-oops will automatically take a snapshot any time you do anything in your Git repo.

basic usage

  • git oops undo will undo the last operation.
  • git oops history shows you the history of all snapshots taken using a curses-based interface and lets you interactively pick one to restore.

advanced usage

  • git oops record manually records a snapshot.
  • git oops restore SNAPSHOT_ID restores a specific snapshot

how it works

when git oops record takes a snapshot, here's what it does:

  1. save your staging area and workdir: It creates a commit for your current staging area and working directory (very similarly to how git stash does).
  2. get HEAD
  3. get all your branches and tags
  4. check for uniqueness: If the snapshot is exactly the same as the previous snapshot, it'll exit
  5. record everything in a commit. Here's an example commit (from this repository). The metadata is stored in the commit message.
FormatVersion: 1
HEAD: refs/heads/main
Index: 20568a3a49feda34ad6aaa3aff7d7a578a8dee0d
Workdir: 4d1a195dc04ab74cfe1cd94da826ce5b0069d264
Refs:
refs/heads/libgit2: c02fc253375108ec797b6af3ca957e8ea0cc36b9
refs/heads/main: 1b4cdfab2900b3b99473560e76e3f91c560364a0
refs/heads/test: 9ac4a5d8e10b04cdddab698e8a9053e7e645543c
refs/heads/test2: 4247707e426f4b890ecd7314376c4d706a2d799d
  1. update the git-undo reference: It updates refs/git-undo to point at the commit it created in step 5.
  2. update the reflog: it updates the reflog for refs/git-undo to include the new commit

More details about other commands:

  • git oops history retrieves the history from the reflog for refs/git-undo
  • git oops restore COMMIT_ID:
    • retrieves COMMIT_ID
    • runs git -c core.hooksPath=/dev/null restore --source WORKDIR_COMMIT
    • runs git -c core.hooksPath=/dev/null restore --staged --source INDEX_COMMIT
    • updates all the branches and tags from the snapshot. It will not delete any branches or tags, to avoid deleting their reflog.
  • git oops history:
    • runs the equivalent of git reflog git-oops to get a list of histories
    • gives you an interactive UI to choose one to restore
  • git oops undo:
    • runs the equivalent of git reflog git-oops to get a list of histories
    • finds the first one where any of your references changed and restores that one
  • git oops init installs the following hooks: post-applypatch, post-checkout, pre-commit, post-commit, post-merge, post-rewrite, post-index-change, reference-transaction
    • when the hooks run, it runs git oops record

idea: make it easier to share broken repo states

You could imagine using this to share repository snapshots with your coworkers, like

you run:

$ git oops record
23823fe
$ git branch my-broken-snapshot 23823fe
$ git push my-broken-snapshot

they run:

# make a fresh clone
$ git clone your-repo
$ git fetch origin my-broken-snapshot
$ git oops restore 23823fe

now they can see what weird state you ended up in and help you fix it!

I think this doesn't quite work as is though.

problems

Current problems include:

  • git oops init overwrites your git hooks and doesn't give you any way to uninstall them. You need to uninstall it manually
  • It doesn't really support multiple undos
  • there's no preview for what it's going to do so it's kind of scary
  • makes all of your commits and rebases slower, in some cases MUCH slower. Maybe Python is not a good choice of language? Not sure.
  • it's mostly untested so I don't trust it
  • probably a million other things

acknowledgements

People who helped: Kamal Marhubi, Dave Vasilevsky, Marie Flanagan, David Turner

Inspired by GitUp, jj, and git-branchless, if you want an undo feature to actually use one of those tools is a better bet.

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages