multiple git repos to single fossil
(1) By anonymous on 2019-12-03 06:39:54 [link] [source]
I'm trying to migrate several git repositories into a single fossil file on trunk while preserving the history.
What I've done is as follows:
mkdir /tmp/t1
cd /tmp/t1
fossil init ~/monorepo.fossil
fossil open ~/monorepo.fossil
echo monorepo >> README.md
fossil add README.md
fossil commit -m "initial commit"
for file in repo1 repo2 repo3 repo4; do ( cd ~/repos/$file && git fast-export --all ) \
| fossil import --git --incremental --rename-master $file ~/monorepo.fossil; done
At this point I have 4 different distinct branches with no common ancestors. When I try to merge any of these branches into trunk, it fails.
$ fossil merge repo1
cannot find a common ancestor between the current checkout and repo1
fossil merge repo1 --baseline 56dc6d3c8fd036b22979cdc759a99a3cb84f3691
lack both primary and secondary files
Another option would be to modify the sqlite directly...I'm brand-new and was looking at the mlink/plink. Any thoughts on how to achieve the single tr?
(2) By Warren Young (wyoung) on 2019-12-03 12:36:38 in reply to 1 [link] [source]
My sense is that this would require an entirely new feature in Fossil, which you could call a blind merge, which wouldn't actually be a merge at all, but a way for one branch to say "My data comes from over there." Another way to think of it is hard links for Fossil repos.
If this is right, then someone just has to want it to exist badly enough to write the code for it. I doubt it's impossible within the current Fossil repo structure.
(3) By tjheeta on 2019-12-05 05:42:22 in reply to 2 [link] [source]
It's definitely possible. After looking through the table structure, it can be done by the following:
- From the UI, cancel the tag trunk on all the repos that were imported.
- From the UI, adjust the timestamp of the default commit.
- From fossil sql, add a link from the initial commit (1), to the imported initial commit (264 in example), with isprim setting 1, and an appropriate julian timestamp.
$ fossil sql
sqlite> select * from event;
// look for the appropriate commit id and julian timestamp (adjust decimal point to be earlier)
sqlite> insert into plink values(1, 264, 1, 2457066.6116782409138, NULL);
$ fossil merge repo1
(4) By tjheeta on 2019-12-05 05:43:12 in reply to 2 [link] [source]
Thanks for the response earlier.
(5) By Stephan Beal (stephan) on 2019-12-05 05:54:28 in reply to 3 [link] [source]
Be aware that the event
table is 100% transient: it is created based off of the artifact state of the database. When you clone or run rebuild the event table is completely recreated, so any changes you make to it will be lost.
(6) By tjheeta on 2019-12-05 06:45:33 in reply to 5 [link] [source]
That's good to know.
In this case, the plink table was the only one that was modified to add a parent to the stranded branch. It appears that the changes have held up over a fossil rebuild.
Ran a "fossil test-integrity --parse ~/tmp.fossil" and it appears to come out clean. I've also made a few commits and it appears the change is stable.
If there's anything else to test, please let me know as I'd hate to lose data.
(7.1) By Stephan Beal (stephan) on 2019-12-05 07:16:31 edited from 7.0 in reply to 6 [link] [source]
plink is also transient. In fact, all content-related tables except blob
are transient. There's no guaranty that they'll survive a rebuild and they certainly won't survive a reconstruct
, nor will they clone from that repo to another one. All such tables are essentially caches for information which is stored in "fossilized" (not db-normalized) form in the blob
table. Every time a fossil-format artifact is injected into the db, fossil normalizes that data and updates any appropriate tables (depending on the artifact type), such as plink, filename, event, etc.
Edit: fossil never updates any such tables without a fossil-format artifact having been introduced to formally introduce the data. All other tables are simply normalized forms of that "formal" data.
(8) By Stephan Beal (stephan) on 2019-12-05 07:28:18 in reply to 7.1 [source]
(Sorry, my morning coffee is still kicking in...)
Just to clarify: what i wrote above applies to "content" tables - those dealing with the versioned content. There are tables, e.g., config and user, which are not versioned and are modified directly via db operations without any fossil-format data being introduced. Such tables are considered to be local state and do not sync via the normal syncing process. Some can be transferred via fossil config push/pull
, but that's not a two-way sync: it's a case of "last one wins."