-1

I have a repo which I use for personal notes. I use the same repo across multiple machines and multiple OSes. The sync happens using git. Each machine has a 5-minute cron job that both pushes and pulls from the (same) repo - that keeps it consistent across all the machines.

I have accumulated thousands of commits over time and I don't really need commits from over a month ago (I have more than a year worth of updates). So I need to squash say first 1000 commits into one without having to change my entire setup by recreating the entire repository and setting up everything again!

What can I do to squash the first 1000 commits into one thus making the repo size smaller?

Vaibhav
  • 628
  • 6
  • 10
  • Have you searched for ”squash first n commits“? I’ve seen them but perhaps with another search term. I would use ‘git commi-tree’. – Guildenstern May 07 '23 at 07:00
  • Duplicate of https://stackoverflow.com/q/435646/8724072. Identical process but different number of commits. This is where editor line numbers are handy. – youngson May 07 '23 at 07:09
  • 2
    Is there a reason for you versioning your notes, or are you only using git as a tool for syncing them and don't care about the commits in the first place? – Kim May 07 '23 at 07:27
  • 2
    What's your objection to having the extra 1000 commits? Trying to eliminate them sounds like an unnecessary misuse of Git. Changing history is going to be a pain in the butt for your push-pull routine no matter how you slice it. So why bother? Also, unless you are storing big binaries such as images in your repo, deleting 1000 commits will not actually make the repo significantly smaller. So the entire proposed exercise sounds fruitless to me. – matt May 07 '23 at 16:24
  • If I squash the first 1000 commits and then push them from Machine A and then pull them on Machine B, what would be the problem? And yes, my notes do have images and stuff which get deleted after they become useless (e.g. I took a quick pic of a contact card and then deleted it later after storing the contact in my phonebook). @Kim I am using git only for syncing, not for versioning. Of course saving older versions helps me go back to some time if I deleted something from the notes but that's only a pleasant side effect. – Vaibhav May 07 '23 at 16:56

2 Answers2

1

Exmaple a tree history: the order is from oldest to newest commit.

We are only able to squash commits newest into a old commit. it means we can squash 1 into 2, or 1, 2 into 3 or 2, 3 in to 4, so forth.

Of course, after squash, commit hash id was squashed into, corresponding to examples above are 2 or 3 or 4, so forth; also will be changed.

(master): m1<--m2<--m3<--f1<--f2<--f3(HEAD)
          6    5    4    3     2    1

you want to squash (4 commits latest) - 4 3 2 1, you can do this

first:

git rebase -i HEAD~4 (1, 2, 3 merge into 4)

second:

popup appear (vim editor), you have to replace pick with s or squash in (3, 2, 1)

finally:

wq!

if you want to push those changes to remote, you must specify -f

Manh Do
  • 111
  • 8
  • That would squash the "last few commits", not the first ones. Given your answer I actually want to merge 6, 5 and 4. – Vaibhav May 07 '23 at 16:57
  • that's impossiable, you only can merge 4, 5 into 6. The order must be new into old – Manh Do May 07 '23 at 18:52
  • I am choosing this answer as the solution because of the above comment. @Manh Do - Could you please edit the answer and add to it the contents of your comment (that it is not possible to do it)? It would be helpful. I believe the reason why its impossible would be that from the beginning of the history, the possibilities of a branch tree (new branches coming out of the main/master branch) is pretty high and in that case, git might not be able to squash commits from the beginning (because that would mean loss of context for branches that split out from that line). – Vaibhav May 13 '23 at 08:10
1

I have provided a script to do this without much hassle, including merges:

https://github.com/eantoranz/git-replay

So.... Check-out a new branch starting from the commit that has the tree that you want as the first commit. Suppose this commit is X

git checkout --orphan new-branch X
git add .
git commit -m "first commit"

Now, use the script

./git-replay HEAD X original-branch

That Will print, in the end, the id of a commit that has a history just like the one you want. Check it and, if you like it, use that commit to set the branch you want there.

eftshift0
  • 26,375
  • 3
  • 36
  • 60