0

I am using Obsidian md with a backup every minute on a git repo. Which means I have a quite big .git folder and want to periodically shorten it, because I'm using quite some images on my notes.

What I would like is to keep only the last 100 commits, and regroup all the other one into a single one 100st commit.

Is that possible with a simple command ? I would like to do it periodically like every month or so, so I'm looking for a simple one, but git gc, git repack and other commands seems not to work.

Thanks in advance !

  • Every minute?! Why so often? – evolutionxbox Oct 09 '22 at 15:49
  • That's because I want it backup while I'm writing note. Most of them are just markdown files but I sometime add some pictures to my notes ! – MathisGauthey Oct 09 '22 at 15:53
  • Squashing commits will make the .git folder BIGGER, at least until the replaced commits are pruned. – amphetamachine Oct 09 '22 at 16:24
  • This same question was asked yesterday. Does this answer your question? [Git: remove commits older than 1 year](https://stackoverflow.com/questions/73994690/git-remove-commits-older-than-1-year) – TTT Oct 09 '22 at 16:30
  • It requires a Python script, why not, but it must exist a simplest way to keep 100 commits and make the 100st like the initial one ? – MathisGauthey Oct 09 '22 at 16:47
  • @MathisGauthey If your history is linear, or all merges never had conflicts to resolve, then you can use `rebase --rebase-merges` without any external tools. The advantage of `git-filter-repo` is it can also handle conflicts, is much faster than rebase, and automatically does garbage collection for you. For only 100 commits though, rebase should be plenty fast enough. You'll still need to do some manual garbage collection when you're done, or you won't realize the space savings right away. – TTT Oct 10 '22 at 01:30
  • git-filter-repo has been recommended, but I don't quite understand how to make it work yet, I'd need to find out. `rebase --rebase-merges` is the full command I need to input ? I don't see anything linked to the 100. And garbage collection ? This is something new for me, I don't know much more than git commit, push and pull simple commands. – MathisGauthey Oct 11 '22 at 08:08
  • Use git for backup (or the way you used it) is not a wise choice. Why not OneDrive or Dropbox? If you really want to use git, consider committing each time you finish an article or pause the writing. Committing based on time (let alone every minute) is irrational and a poor practice. – lzhh Oct 11 '22 at 08:19
  • That's because I need to sync that with my phone, and there is no local syncing good enough for a sync with my phone. Either it is too slow for the svg icons in my icon plugin, or it isn't fast enough for syncing and using both devices almost simultaniously/ – MathisGauthey Oct 12 '22 at 09:02

1 Answers1

0

Rebasing and squashing commits will actually make the .git folder BIGGER, at least until the replaced commits are prune-d. This is because git keeps the commits it "replaces" around after rebasing. See output from reflog.

To keep the history intact, but the .git directory small, you could try using a shallow clone to keep copies of the repo small. This may involve re-cloning (with clone --depth=1) into a different directory.

There's a cheaper way to rebase, and it doesn't involve rebase at all. Restart the git history by periodically doing this:

git reset --soft "$(git rev-list --max-parents=0 HEAD |head -1)"
git commit -m 'First commit message'

Your original solution can be done with a specially-crafed EDITOR command:

#!/bin/bash
NUM_LINES=$(wc -l < "$1")
KEEP=1000
if [[ $NUM_LINES > $KEEP ]]; then
    # [Line numbers shown] Transform:
    # 0001 pick abcdef
    # 0002 pick abcdef
    # .... pick ...
    # 1000 pick abcdef
    # 1001 pick abcdef
    #
    # To:
    # 0001 pick abcdef
    # 0002 f abcdef
    # .... f ...
    # 1000 f abcdef
    # 1001 pick abcdef
    #
    # Importantly, the rebase instruction file cannot begin with a `fixup` instruction.
    exec sed -e "2,$(( NUM_LINES - KEEP ))"'s/^\(pick\|p\) /f/' "$@"
fi

Save it as squash-first-thousand.sh and reference it when you rebase:

EDITOR=/path/to/squash-first-thousand.sh \
git rebase -i "$(git rev-list --max-parents=0 HEAD |head -1)"

You can also use export EDITOR=...

amphetamachine
  • 27,620
  • 12
  • 60
  • 72
  • I'm sorry but I don't understand much there except for the shallow clone, but I can't push from a shallow clone. I don't quite understand reflog, prune, and the EDITOR thing to be honest. I don't use Git as a dev, it is just my way of syncing my notes with Obsidian for now. – MathisGauthey Oct 09 '22 at 17:04