Git Conversion Lazarus
This page has the detailed steps used to convert the Lazarus SVN repro to git.
SubGIT
The initial conversion will be done using TMate Subgit.
Install
Unpack subgit to
~/subgit/subgit-3.3.11Required
An author.txt file
svn-name - git-name <email>Run / main repro
cd ~/subgit/subgit-3.3.11
./bin/subgit configure https://svn.freepascal.org/svn/lazarus laz.git
gedit laz.git/subgit/configAnd add the following (the first line, replaces an existing setting)
[svn]
trunk = trunk:refs/heads/main
gitCommitMessage = %message\\n\\ngit-svn-id: %branch@%revision -\\n
[translate]
eols = false
otherProperties = false
ignores = falseThe translate options prevent .gitignore and .gitattributes. Those can be translated, but will later be replaced...
cp authors.txt laz.git/subgit/authors.txt ./bin/subgit install laz.gitWithout skipping the gitignore/gitattributes, there will be an error at revision 47330. The process will hang. nterrupt it and edit
gedit lazarus.git/svn/.metadataand set branches-maxRev and tags-maxRev to 47332 (it should be at 47330) https://stackoverflow.com/questions/18918215/skip-revisions-when-installing-subgit-repository Continue with
./bin/subgit install laz-bin.gitStop the daemon
./bin/subgit shutdown laz-bin.git/Run / binaries repro
./bin/subgit configure https://svn.freepascal.org/svn/lazarus laz-bin.git gedit laz-bin.git/subgit/config
[svn]
gitCommitMessage = %message\\n\\ngit-svn-id: %branch@%revision -\\n
trunk = binaries:refs/heads/main cp authors.txt laz-bin.git/subgit/authors.txtfollow the steps above
Run / website repro
./bin/subgit configure https://svn.freepascal.org/svn/lazaruswebsite laz-web.git gedit laz-web.git/subgit/config
[svn]
gitCommitMessage = %message\\n\\ngit-svn-id: %branch@%revision -\\n
trunk = trunk:refs/heads/main cp authors.txt laz-web.git/subgit/authors.txtfollow the steps above
Part 2
- Updating gitignore
- Prefixing all issue references with #
- translating svn revisions to git hashes
Set a git user
git config --local user.email "lazarus@lazarus-ide.org"
git config --local user.name "lazarus"Clean out left overs from subgit
git for-each-ref --format="%(refname)" refs/svn/ | xargs -n 1 git update-ref -dClean left overs from binaries
There are a few tags, that lead to binaries (gdb.exe) ending up in the data
git tag -d binaries_0_9_26
git tag -d binaries_0_9_26_2
git tag -d binaries_0_9_28
git tag -d binaries_0_9_30
git tag -d binaries_0_9_30_2
git tag -d binaries_0_9_30_2RC1
git tag -d binaries_1_0Updating gitignore/gitattributes / Prefix issues with #
The below combines the 2 steps. It can be run in 2 separate calls.
It will run for about one hour.
FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --index-filter ' cp ~/subgit/subgit-3.3.11/.gitignore ~/subgit/subgit-3.3.11/.gitattributes . ; git add .gitignore .gitattributes ' --msg-filter ' perl -ne "while (s/((?:iss?ues?|[ (](?:bugs?|mantis|fix|fixes|patch)\b)(?: +id)?[ :]+(?:#?0*[1-9][0-9]{2,4}(?: *(?:[ ,]| and ) *))*)(0*[1-9][0-9]{2,4})\b/\1#\2/i) {}; print" ' -f -- --all FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --msg-filter ' perl -ne "while (s/((?:iss?ues?|[ (](?:bugs?|mantis|fix|fixes|patch)\b)(?: +id)?[ :]+(?:#?0*[1-9][0-9]{2,4}(?: *(?:[ ,]| and ) *))*)(0*[1-9][0-9]{2,4})\b/\1#\2/i) {}; print" ' -f -- --allCleanup
git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git reflog expire --expire=now --all ;git gc --prune=nowTranslating references to svn rev (r12345) to #hash
This must be the very last filter-branch. As each filter-branch creates new hashes for the commits, and that would invalidate the hash refs created here.
- The first batch will update only commits it branch main.
This will also only be references to other commits in main.
Merges from branches to main can not be updated.
- The 2nd batch will update only commits in branches. This means the hashes for the main branch will be left intact.
This will update merges from main to fixes
To verify the 2nd batch does not update the main branch compare the hash for git log -n1 main. It should not be changed by the 2nd batch.
rm -rf /tmp/rmap
mkdir /tmp/rmap
git rev-list main | xargs -L1 /bin/sh -c 'a=$( git log -n1 --pretty='%B' $0 | grep "git-svn-id: .*@[0-9][0-9]* " | sed "s/.*@\([0-9]*\) .*/\1/" ) ; echo $0 > /tmp/rmap/$a'
git rev-list main | xargs -L1 /bin/sh -c 'echo 1 > /tmp/rmap/m_$0' FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --msg-filter 'perl -wne "use strict;
unless ( -e qq#/tmp/rmap/m_\$ENV{GIT_COMMIT}# ) { print; next; }
my %f; foreach(/(?:(?:commit|rev|revisions?|revision\(s\)|revert|reverted) +| r)([1-9][0-9]{3,4}\b(?:[\/,-] *[1-9][0-9]{3,4}\b)*)\b/gi) {
my \$rvl=\$1;
foreach my \$a (split / *[\/,] */, \$rvl) {
unless (\$f{\$a}){
\$f{\$a}=q/#/;
my(\$a1, \$a2) = split / *- */, \$a;
my \$c; my \$rh; if( open \$rh, q/</, qq#/tmp/rmap/\$a1#) { \$c=<\$rh>; chomp \$c; }
my \$h; if(\$c && (open \$h, q/</, qq#../map/\$c#)) {
\$c=<\$h>; chomp \$c; \$c = q/#/.substr \$c, 0,10;
if (\$a2) {
my \$c2; my \$rh2; if( open \$rh2, q/</, qq#/tmp/rmap/\$a1#) { \$c2=<\$rh2>; chomp \$c2; }
my \$h; if(\$c2 && (open \$h, q/</, qq#../map/\$c2#)) { \$c2=<\$h>; chomp \$c2;
\$c = \$c.q/-#/.substr( \$c2, 0,10);
}
else { \$c = \$c.q/..# / unless \$c eq q/#/; warn q/MAP2 FAIL /.\$c2 }
}
\$f{\$a}=\$c;
}
else {warn q/MAP1 fail/.\$a;}
}}
}
foreach my \$k (keys %f) { my \$v = \$f{\$k};
unless (\$v eq q/#/) { s/([ r,\/]\${k}\b)/\$1 \$v/g; }
}
warn \$_ if keys %f;
print; "
' -f -- --all git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d rm -rf /tmp/rmap
mkdir /tmp/rmap
git rev-list --all | xargs -L1 /bin/sh -c 'a=$( git log -n1 --pretty='%B' $0 | grep "git-svn-id: .*@[0-9][0-9]* " | sed "s/.*@\([0-9]*\) .*/\1/" ) ; echo $0 > /tmp/rmap/$a'
git rev-list main | xargs -L1 /bin/sh -c 'echo 1 > /tmp/rmap/m_$0' FILTER_BRANCH_SQUELCH_WARNING=1 git filter-branch --msg-filter 'perl -wne "use strict;
if ( -e qq#/tmp/rmap/m_\$ENV{GIT_COMMIT}# ) { print; next; }
my %f; foreach(/(?:(?:commit|rev|revisions?|revision\(s\)|revert|reverted) +| r)([1-9][0-9]{3,4}\b(?:[\/,-] *[1-9][0-9]{3,4}\b)*)\b/gi) {
my \$rvl=\$1;
foreach my \$a (split / *[\/,] */, \$rvl) {
unless (\$f{\$a}){
\$f{\$a}=q/#/;
my(\$a1, \$a2) = split / *- */, \$a;
my \$c; my \$rh; if( open \$rh, q/</, qq#/tmp/rmap/\$a1#) { \$c=<\$rh>; chomp \$c; }
if (\$c) { unless ( -e qq#/tmp/rmap/m_\$c# ) {
my \$h; if(open \$h, q/</, qq#../map/\$c#) { \$c=<\$h>; chomp \$c; }
}}
if(\$c ) {
\$c = q/#/.substr \$c, 0,10;
if (\$a2) {
my \$c2; my \$rh2; if( open \$rh2, q/</, qq#/tmp/rmap/\$a1#) { \$c2=<\$rh2>; chomp \$c2; }
if (\$c2) { unless ( -e qq#/tmp/rmap/m_\$c2# ) {
my \$h; if(open \$h, q/</, qq#../map/\$c2#) { \$c2=<\$h>; chomp \$c2; }
}}
if(\$c2) { \$c = \$c.q/-#/.substr( \$c2, 0,10); }
else { \$c = \$c.q/..# / unless \$c eq q/#/; warn q/MAP2 FAIL /.\$c2 }
}
\$f{\$a}=\$c;
}
else {warn q/MAP1 fail/.\$a;}
}}
}
foreach my \$k (keys %f) { my \$v = \$f{\$k};
unless (\$v eq q/#/) { s/([ r,\/]\${k}\b)/\$1 \$v/g; }
}
warn \$_ if keys %f;
print; "
' -f -- --all git for-each-ref --format="%(refname)" refs/original/ | xargs -n 1 git update-ref -d
git reflog expire --expire=now --all ;git gc --prune=now
rm -rf /tmp/rmapUpdating tags
This must be done after all filter-branches
- Annotate all tags.
- Create some more tags
This needs the git user being set
git for-each-ref --format="%(refname:short)" refs/tags/ | xargs -L1 /bin/sh -c 'git tag -f -a $0 -m $0 $0 ' git rev-list --in-commit-order --reverse fixes_2_2..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-2_3" -m "main to version 2.3" $0'
git rev-list --in-commit-order --reverse fixes_2_0..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-2_1" -m "main to version 2.1" $0'
git rev-list --in-commit-order --reverse fixes_1_8..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-1_9" -m "main to version 1.9" $0'
git rev-list --in-commit-order --reverse fixes_1_6..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-1_7" -m "main to version 1.7" $0'
git rev-list --in-commit-order --reverse fixes_1_4..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-1_5" -m "main to version 1.5" $0'
git rev-list --in-commit-order --reverse fixes_1_2..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-1_3" -m "main to version 1.3" $0'
git rev-list --in-commit-order --reverse fixes_1_0..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-1_1" -m "main to version 1.1" $0'
git rev-list --in-commit-order --reverse fixes_0_9_30..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-0_9_31" -m "main to version 0.9.31" $0'
git rev-list --in-commit-order --reverse fixes_0_9_28..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-0_9_29" -m "main to version 0.9.29" $0'
git rev-list --in-commit-order --reverse fixes_0_9_26..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-0_9_27" -m "main to version 0.9.27" $0'
git rev-list --in-commit-order --reverse fixes_0_9_24..main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-0_9_25" -m "main to version 0.9.25" $0'
git rev-list --in-commit-order --reverse main | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "main-0_0" -m "main init" $0'
git rev-list --in-commit-order --reverse main..fixes_2_2 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-2_2" -m "fixes 2.2 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_2_0 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-2_0" -m "fixes 2.0 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_1_8 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-1_8" -m "fixes 1.8 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_1_6 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-1_6" -m "fixes 1.6 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_1_4 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-1_4" -m "fixes 1.4 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_1_2 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-1_2" -m "fixes 1.2 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_1_0 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-1_0" -m "fixes 1.0 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_0_9_30 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-0_9_30" -m "fixes 0.9.30 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_0_9_28 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-0_9_28" -m "fixes 0.9.28 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_0_9_26 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-0_9_26" -m "fixes 0.9.26 branch" $0'
git rev-list --in-commit-order --reverse main..fixes_0_9_24 | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-fixes-0_9_24" -m "fixes 0.9.24 branch" $0'
git rev-list --in-commit-order --reverse main..free-sparta | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-free-sparta" -m "free-sparta branch" $0'
git rev-list --in-commit-order --reverse main..gtk-splitup | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-gtk-splitup" -m "gtk-splitup branch" $0'
git rev-list --in-commit-order --reverse main..lcl-smartlink | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-lcl-smartlink" -m "lcl-smartlink branch" $0'
git rev-list --in-commit-order --reverse main..listviewsortindicator | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-listviewsortindicator" -m "listviewsortindicator branch" $0'
git rev-list --in-commit-order --reverse main..macosfullkeyboardaccess | head -n 1 | xargs -L1 /bin/sh -c 'git tag -a "t-macosfullkeyboardaccess" -m "macosfullkeyboardaccess branch" $0'Finish
edit HEAD to point to main
gedit HEAD git remote add origin https://gitlab.com/freepascal.org/lazarus-ide/lazarus_test_conversion_X.git git push --all origin
git push --tags originOn gitlab
- Settings / Repository
- set default gitlab branch
- no autoclose issues on default branch // decide later - set "reject unverified users"
- protect branches * // no force push
- protect tags: fixes* lazarus* release* main* // maintainers only
- set default gitlab branch
- Settings / Integrations
- External wiki
- Settings / General
- Disable Wiki, Snippets, Papges, Requirements, Operations, Service Desk, Container, Packages
For now also CI, until we use it - Merge request approvals: Enable "Prevent users from modifying MR approval rules"
- set the avatar
- Add "description"
- Make public
- Disable "Users can request access"
- Disable Wiki, Snippets, Papges, Requirements, Operations, Service Desk, Container, Packages
Comparing data before/after filter-branch
With subject line / Will show changes in subject
git log --pretty='format:%ae %an %cd %s %d' --graph --all > ../log.txtWithout subject line / Should have no diff
- This compares the graph and committers => Thus it will show if all commits are present, and if all branches are correct
git log --pretty='format:%ae %an %cd %d' --graph --all > ../log.txt- compare the changes to files (gitignore / gitattributes will diff for the top commit(s)) / --graph can be added too
(slow)
git log --all --pretty='%ae %an %cd %d' --stat > ../statlog.txt- Compare the overall amount of lines in the log.
git log --all | wc -lMake sure you do that after "clean up" in each step. Otherwise the internal subgit or filter-branch revs will go into the compare.
Also "removing the binaries" introduces a diff.
Data
Please mail me for any changes. Do not make changes here. Otherwise the changes will not make it into the conversion.
.gitignore
**/*.o
**/*.ppu
**/*.exe
**/*.bak
**/*.diff
**/*.patch
**/units/
**/lib/
**/*;[1-9]
**/*.~*
**/*.*~
**/*.fpcunit.ini
**/*.lps
**/*.compiled
/docs/chm/**/*.chm
/docs/chm/**/*.xct
/docs/chm/**/*.kwd
/docs/chm/**/*.txt
/libeay32.dll
/ssleay32.dll
/lazarus.cfg
ide/revision.inc
!**/patches/*.patch
!**/patches/*.diff.gitattributes
* text=auto !eol
**/*.pp text
**/*.pas text
**/*.inc text
**/*.lfm text
**/*.lrs text
**/*.lps text
**/*.lpr text
**/*.lpi text
**/*.lpk text
**/*.lpl text
**/*.lrj text
**/*.dpr text
**/*.dfm text
**/*.pot text
**/*.po text
**/*.rc text
**/*.txt text
**/*.txt.sample text
**/*.ini text
**/*.cfg text
**/*.iss text
**/*.isl text
**/*.xml text
**/*.xsl text
**/*.html text
**/*.css text
**/*.php text
**/*.js text
**/.htaccess text
**/*.patch text
**/*.md text
**/*.bat text
**/*.sh text
**/*.compiled text
**/*.bdsproj text
**/*.plist text
**/*.h text
**/*.c text
**/*.cpp text
**/*.in text
**/*.xpm text
**/*.svg text
**/Makefile text
**/Makefile.compiled text
**/Makefile.fpc text
**/*.exe -text
**/*.dll -text
**/*.so -text
**/*.gif -text
**/*.jpg -text
**/*.ico -text
**/*.bmp -text
**/*.res -text
**/*.ttf -text
**/*.cur -text
**/*.db3 -text
**/*.dbf -text
**/*.mbf -text
**/*.mdx -text
**/*.fbk -text
**/*.odt -text
**/*.ods -text
**/*.odg -text
**/*.odp -text
**/*.xls -text
**/*.pdf -text
**/*.zip -text
**/*.rar -text
**/*.tar -text
**/*.tgz -text
**/*.gz -text
**/*.icns -text
**/*.dcr -text
components/aggpas/**/*.ppm -text
**/*.app/Contents/MacOS/* -textFrom the Free Pascal wiki, page "Git Conversion Lazarus", as it stood on 2021-07-28 after a change by Martin, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's Licensing page. If you have concerns about this material, message the admin.