0

I'm almost sure about the answer but I'm asking anyway

I need to publish the Git history of a repo to a new server, but only from now on. That is, squash the current commit log to an initial commit and from now on make a new history. Ideally the current server should keep the full history and new commits, while the second server only the squashed one and from now on.

To my knowledge the purpose of git is to avoid this kind of messup, but I might not be aware of all the features :)

EDIT: I probably wasn't clear enough: I'd like to keep the current history on the actual server, start a new history on a new mirrored remote server. I don't want to start over with everything

Maxxer
  • 1,038
  • 1
  • 18
  • 37
  • 1
    Just for my understanding. Won't removing git and `git init` again do what you need? As it had no history of your tree, won't it just start from scratch? – clamentjohn Jul 30 '18 at 16:06
  • [Yes it will](https://stackoverflow.com/a/9844177/542251) – Liam Jul 30 '18 at 16:09
  • Possible duplicate of [how to create a new git repository from an existing one](https://stackoverflow.com/questions/9844082/how-to-create-a-new-git-repository-from-an-existing-one) – Liam Jul 30 '18 at 16:09
  • thanks, but that's not what I need. I updated the question to clarify – Maxxer Jul 30 '18 at 16:13
  • History is commits; commits are the history. Commit hash IDs encode everything *about* the commit. Make a new repository with a new commit that contains the last snapshot of an existing repository, and you have a new, different commit that ***is*** a new, different history. These two histories will remain different forever. That's your choice: new history, or not. – torek Jul 30 '18 at 16:49
  • "*I need to publish the Git history of a repo to a new server, but only from now on*" I have to ask, why? If you're Open Sourcing and are embarrassed about past commits, there are more elegant ways to clean them up. – Schwern Jul 30 '18 at 17:11

1 Answers1

0

tl;dr You can, but it's a pain and throws away most of the value of Git.

I'm going to guess you're making a private repository public and there's some things in there you'd rather not have the world see. Passwords, trade secrets, swearing at customers, etc... Instead of throwing out your history before publishing, rewrite your history to make it safe to publish. Use git filter-branch and git rebase -i to selectively rewrite history and the BFG Repo Cleaner to remove files en masse.

Then you can publish your freshly scrubbed, less embarrassing repository.


I think you want two repositories like this.

A - B - C - D - E - F - G [master]

            Q - E - F - G [master]

Where A - B - C - D is the unsquashed history, Q is the squashed commit, and E - F - G are commits going forward.

The best you can get is this.

A - B - C - D - E - F - G [master]

            Q - E1 - F1 - G1 [master]

Where E1 - F1 - G1 are the same content as E - F - G but they have different commit IDs. Very different commit IDs. Totally unrelated commit IDs. It's messy and it throws away all the power of Git.

A Git commit is the content of that commit plus all previous commits. The commit ID is a checksum of all the content of the commit, things like the date, author, and log message, and the commit ID of the parent commit(s). If you change the repository by squashing, you change the commit ID and you change the commit ID of every commit that goes on top of it. If you change the commit ID Git won't consider them to be the same commits anymore.

To accomplish what you want, you have to essentially replace each commit after the squash as if it were a fresh commit on top of your new repository. git cherry-pick will do this. These commits will get fresh commit IDs, so Git won't recognize them as the same commits. You'll have to manually manage the last time you did a cherry pick.

For example, you'd have the original repository set up as a remote of the squashed repository and a tag to track the sync point.

              [sync]
A - B - C - D [origin/master]

            Q [master]

Periodically you'd git fetch to get updates.

             [sync]
A - B - C - D - E - F [origin/master]

            Q [master]

Then you'd cherry pick from the sync point.

git cherry-pick sync..origin/master

             [sync]
A - B - C - D - E - F [origin/master]

            Q - E1 - F1 [master]

And update the sync point.

                      [sync]
A - B - C - D - E - F [origin/master]

            Q - E1 - F1 [master]

Branches will be interesting to deal with. It's possible you can use git rebase instead which can deal with branches.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Wow, thank you very much for the detailed answer! So they're basically two different repo I'd have to manually keep in sync. What I'm missing is how am I supposed to *move* the tag once the sync has been done. Tags cannot be deleted AFAIK, you suggest to use a different tag every time the sync is done? – Maxxer Jul 31 '18 at 10:01
  • @Maxxer A tag is just a label pointing to a commit. Branches are also just labels pointing to a commit. The difference is a branch label (Git calls them "heads") will move automatically when you commit while a tag will stay put. Both can be moved arbitrarily. `git tag -f `. But again, this is all a very bad idea. I suspect you have an [XY Problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). You're asking about your solution but haven't told us the problem. You'd be better off telling us about the problem you're trying to solve with this solution. – Schwern Jul 31 '18 at 20:53
  • You perfectly hit the problem: I'd like to publish a clean repository. Not because there's any swearing or anything, just because I want a *fresh* history for the new repo. So I think your answer is the best solution – Maxxer Aug 01 '18 at 05:35
  • @Maxxer Why do you want a fresh history, or rather no history, for an existing project? The change history is valuable information to understand the code. The code tells the what, the history tells the why. – Schwern Aug 01 '18 at 06:50
  • that's why I'd like to keep the history on our repo :) – Maxxer Aug 01 '18 at 07:53
  • @Maxxer What's this other repo with no history meant for? – Schwern Aug 01 '18 at 17:05