Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

shun a whole commit in fossil

I have added a directory of files in my fossil repository, but:

  1. the files contained occupy way more space than I expected
  2. I realized afterward that adding it was completely superfluos.

So now I find myself with a repository one order of magnitude bigger than it needs to be to contain files that were never useful. The whole directory has been included in a single commit, nothing else has been done in that commit, and has never modified since, but I had to do other commits afterward (after getting more confident with fossil, I know that I could have used undo before doing anything else, but at the time I wasn't conscious of the posibility).

The only way I found to do the job is to perform a shun on the data to remove them, but I also found online that this operation can wreak havoc in the database. Given that is a work related repository, I'm concerned about causing damages.

Is there a way to get rid of those files that is safe and will not leave the database in a corrupted/full of warning state?

like image 270
EnricoGiampieri Avatar asked Jan 05 '23 08:01

EnricoGiampieri


1 Answers

If the bad checkin exists only in your repository (or your repository plus a server) and has not been pulled by other users, the simplest solution is to use fossil purge.

Use fossil purge checkins <tag> to move those checkins to the "graveyard"; the <tag> part can also be the hash of a checkin, not just a symbolic tag. Be aware that if you specify a branch, the entire branch will be purged; even if you don't specify a branch, all descendant of the checkin will be purged (as they depend on it). Once you've confirmed that everything is in order, use fossil purge obliterate to get rid of the graveyard if you need to free up the disk space. If you don't need the disk space, you can let the graveyard sit around for a while until you're certain that everything is okay. Consult fossil help purge for further options.

You may want to keep a backup of the repository (it's just a single file, you can just copy it) for a bit in case something didn't go right.

The shunning mechanism exists only to purge artifacts globally and is meant to be used on a central server as a last resort: it will prevent those artifacts from being propagated anymore to other users via that server. If your changes are local only or if you have access to all the servers and can use fossil purge instead, shunning is unnecessary.


If you actually need to purge something in the middle of a branch, additional steps are required.

  1. Make a backup of the repository file, as you're going to do non-trivial surgery on it.
  2. Use fossil update to move to the checkin just prior to the defective one.
  3. Use fossil merge --cherrypick to copy the first "good" checkin. Do fossil commit --allow-fork to commit the copy of that checkin; the editor should be prepopulated with the original commit message. You will be prompted to confirm that you don't want to change the commit message. Press "y".
  4. Repeat step 3 (fossil merge --cherrypick + fossil commit) for all remaining "good" checkins. You won't need --allow-fork for these.

You should now have a fork with all the checkins that you want to preserve and a separate fork with the bad checkin and the original version of the good ones. Verify the graph in fossil ui to see that everything is in order. Once that is done, use fossil purge to get rid of the bad checkin and its descendants as described above.

The process in steps 3+4 can be automated with a shell script:

#!/bin/sh
set -e
for commit in "$@"; do
  fossil merge --cherrypick "$commit"
  echo yes | VISUAL=true fossil commit --allow-fork
done

Put this in an file, say fossil-replay.sh, make it executable, then use fossil-replay.sh commit1 commit2 ... commitn to replay commit1 through commitn from the current position in the repository. Obviously, replace commit1 etc. with the actual commit hashes.

like image 176
Reimer Behrends Avatar answered Jan 14 '23 08:01

Reimer Behrends