OpenBagTwo / gsb

A tool for managing incremental backups of your save states using Git!
https://openbagtwo.github.io/gsb/
GNU General Public License v3.0
0 stars 0 forks source link

Rewinding fails when reverting to a non-GSB-managed backup #28

Closed OpenBagTwo closed 11 months ago

OpenBagTwo commented 11 months ago

Summary

Attempting to rewind to a backup prior to gsb onboarding results in the error:

[Errno 2] No such file or directory: '/path/to/repo/.gsb_manifest'

Environment and Version

Steps to Reproduce

  1. Initialize gsb in an existing git repo
  2. Do stuff
  3. Use gsb history -gav to find a pre-gsb commit to restore to
  4. Rewind to that commit by hash, e.g. gsb rewind abcdef01

The result is the following output:

Backing up any unsaved changes before rewinding to 4117be37
[Errno 2] No such file or directory: '/path/to/repo/.gsb_manifest'
ERROR:gsb:[Errno 2] No such file or directory: '/path/to/repo/.gsb_manifest'

and the repo is left in an uncommitted state

Workaround

This can be cleaned up manually with git:

  1. git reset -- .gsb_manifest .gitignore
  2. git checkout .gsb_manifest .gitignore
  3. gsb backup --tag "Rewind to old backup"

Severity

Painful because if you're rewinding to a non-gsb-managed backup, then you must have familiarity with git and you should be able to dig yourself out of your hole.

I am concerned about the rewinding of the .gsb_manifest, but I think that's okay too. Let's play out a scenario:

  1. Alex (is playing Minecraft and) inits gsb in her saves folder, starting by telling it to back up just one world.
  2. Alex creates a second world and adds it to the manifest (see also #27)
  3. Alex plays for a while and then wants to restore to the old save to check something out
    • gsb rewind will then completely delete the new world
    • the manifest will then not even list the new world... but that's fine because there's no world to list
  4. Alex grabs what she needs from the old world and rewinds back to the pre-rewind state, the new world is restored, as is the full manifest. All is right with the world.

Now let's consider what would have happened if the manifest and the ignore hadn't been reverted:

But what if there were changes to .gitignore? :thinking:

Okay, new scenario, managing with git:

openbagtwo@computer ~ $ mkdir ploopy
openbagtwo@computer ~ $ cd ploopy/
openbagtwo@computer ~/ploopy $ git init
Initialized empty Git repository in ~/ploopy/.git/
openbagtwo@computer ~/ploopy $ touch .gitignore
openbagtwo@computer ~/ploopy $ touch doink
openbagtwo@computer ~/ploopy $ git add .
openbagtwo@computer ~/ploopy $ git commit -m "First"
[main (root-commit) 6946f50] First
 2 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 doink
openbagtwo@computer ~/ploopy $ echo "doink\n" >> ".gitignore"
openbagtwo@computer ~/ploopy $ echo "hello\n" >> "doink"
openbagtwo@computer ~/ploopy $ git add .
openbagtwo@computer ~/ploopy $ git commit -m "Ignore doink"
[main fa70be2] Ignore doink
 2 files changed, 2 insertions(+)
openbagtwo@computer ~/ploopy $ git reset --hard HEAD^1
HEAD is now at 6946f50 First
openbagtwo@computer ~/ploopy $ git reset --soft ORIG_HEAD
openbagtwo@computer ~/ploopy $ git add .
openbagtwo@computer ~/ploopy $ git commit -m "What does this button do"
[main 48dfb27] What does this button do
 2 files changed, 2 deletions(-)
openbagtwo@computer ~/ploopy $ git reset --hard HEAD^1
HEAD is now at fa70be2 Ignore doink
openbagtwo@computer ~/ploopy $ git reset --soft ORIG_HEAD
openbagtwo@computer ~/ploopy $ git add .
openbagtwo@computer ~/ploopy $ git commit -m "Where are we now?"
[main b3ae704] Where are we now?
 2 files changed, 2 insertions(+)
openbagtwo@computer ~/ploopy $ cat doink
hello\n

So, I learned a few things:

  1. Rewinding a repo with an ignored file will leave that ignored file alone, even if it wasn't always ignored
  2. This does mean that the new file state will be in the restored commit history (bad if you're trying to keep large files or secrets out of the history!)
  3. echo "\n" does not write a newline :scream: (#TIL: use printf)

Desired Outcome

Based on the experimentation with .gitignore, the solution should be:

  1. By default, do not restore .gitignore and .gsb_manifest when doing a rewind
  2. But provide an option to reset these files as well

Urgency

This should implemented into the release-staging PR (#26)

Notes