Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: svn-all-fast-export/svn2git
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 1.0.14
Choose a base ref
...
head repository: svn-all-fast-export/svn2git
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on May 1, 2019

  1. Revert Maintain annotated tags throughout incremental runs #60

    Revert MR # 60 Maintain annotated tags throughout incremental runs
    
    Due to compile error
    tnyblom committed May 1, 2019
    Copy the full SHA
    58378dc View commit details

Commits on May 9, 2019

  1. compile fix.

    root authored and tnyblom committed May 9, 2019
    Copy the full SHA
    d333319 View commit details
  2. compile fix.

    root authored and tnyblom committed May 9, 2019
    Copy the full SHA
    d2b6ef4 View commit details
  3. Copy the full SHA
    3d583c8 View commit details

Commits on May 15, 2019

  1. Create .travis.yaml

    tnyblom committed May 15, 2019
    Copy the full SHA
    7ed33c6 View commit details

Commits on Jul 1, 2019

  1. Add simple Dockerfile

    Mathieu LAUDE authored and tnyblom committed Jul 1, 2019
    Copy the full SHA
    bdd0868 View commit details
  2. Adding some documentation to run from Docker.

    Mathieu LAUDE authored and tnyblom committed Jul 1, 2019
    Copy the full SHA
    3f965dd View commit details

Commits on Aug 6, 2019

  1. Add basic documentation for rules

    ad1217 authored and tnyblom committed Aug 6, 2019
    Copy the full SHA
    5392048 View commit details

Commits on Feb 9, 2020

  1. Log message when identity map doesn't have any valid lines

    Brad Milne authored and tnyblom committed Feb 9, 2020
    Copy the full SHA
    59b3803 View commit details
  2. Use svn_repos_open() for Subversion 1.6

    alef authored and tnyblom committed Feb 9, 2020
    Copy the full SHA
    f5bd7b0 View commit details

Commits on Feb 10, 2020

  1. empty-dirs option now manages existing folder becaming empty and merg…

    …ing with empty fodlers
    eric-h-itesoft authored and tnyblom committed Feb 10, 2020
    Copy the full SHA
    189d926 View commit details
  2. Copy the full SHA
    54a8846 View commit details
  3. Copy the full SHA
    37695d3 View commit details

Commits on Feb 11, 2020

  1. Merge pull request #88 from svn-all-fast-export/simple-github-actions-ci

    Simple CI based on GitHub Actions (for #87)
    hartwork authored Feb 11, 2020
    Copy the full SHA
    cac4fde View commit details

Commits on Apr 14, 2020

  1. Add Bats tests

    Vampire authored and tnyblom committed Apr 14, 2020
    Copy the full SHA
    c5c2f21 View commit details

Commits on Apr 15, 2020

  1. Copy the full SHA
    1090a19 View commit details
  2. Copy the full SHA
    1b06747 View commit details
  3. Copy the full SHA
    34c2d55 View commit details

Commits on Apr 17, 2020

  1. Add some tests for empty-dirs parameter

    Vampire authored and tnyblom committed Apr 17, 2020
    Copy the full SHA
    9da781b View commit details
  2. Do not dump added directories multiple times if svn-properties or emp…

    …ty-dirs is used
    Vampire authored and tnyblom committed Apr 17, 2020
    Copy the full SHA
    0833cc2 View commit details

Commits on Apr 18, 2020

  1. Copy the full SHA
    c384145 View commit details
  2. If svn-ignore should have added a .gitignore file, do not overwrite i…

    …t with an empty one
    Vampire authored and tnyblom committed Apr 18, 2020
    Copy the full SHA
    1842681 View commit details
  3. Add nested variations of tests

    Vampire authored and tnyblom committed Apr 18, 2020
    Copy the full SHA
    f8bb129 View commit details

Commits on Apr 19, 2020

  1. Fix .gitignore handling in root directory

    Vampire authored and tnyblom committed Apr 19, 2020
    Copy the full SHA
    60bfc16 View commit details
  2. Remove an empty directory .gitignore placeholder once the directory b…

    …ecomes non-empty
    Vampire authored and tnyblom committed Apr 19, 2020
    Copy the full SHA
    955a9e7 View commit details
  3. Add gitignore placeholders for empty directories in branches when usi…

    …ng svn-branches and empty-dirs parameter
    Vampire authored and tnyblom committed Apr 19, 2020
    Copy the full SHA
    359dfe0 View commit details

Commits on Apr 20, 2020

  1. Copy the full SHA
    fcb62af View commit details
  2. Fix missing .gitignore in empty dirs on dir rename

    The commandline option --empty-dirs now also has effect when a directory
    is moved in svn.
    mbaschnitzi authored and tnyblom committed Apr 20, 2020
    Copy the full SHA
    0498b68 View commit details
  3. Add test that copying a directory with empty sub-dirs should put empt…

    …y .gitignore files to empty directories with empty-dirs parameter
    Vampire authored and tnyblom committed Apr 20, 2020
    Copy the full SHA
    572a8ba View commit details
  4. Copy the full SHA
    ece0088 View commit details

Commits on May 1, 2020

  1. Fix some typos in the README and add a pointer to where annotated tags

    are to be found after the conversion.
    uqs authored and tnyblom committed May 1, 2020
    Copy the full SHA
    d8084f9 View commit details

Commits on Jul 2, 2021

  1. Support git default branch name

    - Instead of master use the `init.defaultBranch`
      if set.
    Gabriel Nützi authored and tnyblom committed Jul 2, 2021
    Copy the full SHA
    c1b5012 View commit details
  2. Error out if error happens in fast import process

    Gabriel Nützi authored and tnyblom committed Jul 2, 2021
    Copy the full SHA
    58839fa View commit details

Commits on Jul 5, 2021

  1. Copy the full SHA
    381be06 View commit details

Commits on Jul 15, 2021

  1. Notes on end slash requirement

    gabyx authored and tnyblom committed Jul 15, 2021
    Copy the full SHA
    71d254e View commit details

Commits on Sep 27, 2021

  1. Revert "Error out if error happens in fast import process"

    This reverts commit 58839fa.
    tnyblom committed Sep 27, 2021
    Copy the full SHA
    6b987ad View commit details

Commits on Dec 25, 2022

  1. use ubuntu 22.04

    m-tmatma authored and tnyblom committed Dec 25, 2022
    Copy the full SHA
    2933904 View commit details
  2. use qt5-qmake

    m-tmatma authored and tnyblom committed Dec 25, 2022
    Copy the full SHA
    f28cb92 View commit details
  3. update actions version

    m-tmatma authored and tnyblom committed Dec 25, 2022
    Copy the full SHA
    0b8d171 View commit details
  4. add build matrix

    m-tmatma authored and tnyblom committed Dec 25, 2022
    Copy the full SHA
    98e04b4 View commit details

Commits on Feb 27, 2023

  1. Add CI for Dockerfile

    TWiStErRob authored and tnyblom committed Feb 27, 2023
    Copy the full SHA
    d76d48e View commit details
  2. Copy the full SHA
    068dd31 View commit details

Commits on Apr 26, 2025

  1. build.yaml: Replace dead ubuntu-18.04 by current ubuntu-24.04

    Package subversion turned out tonot be installed
    with ubuntu-24.04.
    hartwork committed Apr 26, 2025
    Copy the full SHA
    6afbec6 View commit details
  2. Copy the full SHA
    3772120 View commit details
  3. build.yaml: Run once a week to detect breakage early

    Some part of below our feet is always moving, and when
    that move breaks something for us, we'll now know in time.
    hartwork committed Apr 26, 2025
    Copy the full SHA
    4a4ddfa View commit details
  4. Copy the full SHA
    b1946fd View commit details
  5. Copy the full SHA
    205f581 View commit details
  6. Copy the full SHA
    7ec3d7f View commit details

Commits on Apr 27, 2025

  1. Copy the full SHA
    e5fdecd View commit details
  2. Copy the full SHA
    eee16fb View commit details
103 changes: 103 additions & 0 deletions .github/workflows/build.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
#
# Copyright (C) 2020 Sebastian Pipping <sebastian@pipping.org>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

name: Build (Linux, Ubuntu)

on:
pull_request:
push:
schedule:
- cron: '0 2 * * 5' # Every Friday at 2am
workflow_dispatch:

# Reduce permissions to minimum for security
permissions:
contents: read

jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- runs-on: ubuntu-24.04
qt_major: 6
qt_qmake: qmake6
qt_packages: qmake6 qt6-base-dev qt6-5compat-dev
- runs-on: ubuntu-24.04
qt_major: 5
qt_qmake: qmake
qt_packages: qt5-qmake qtbase5-dev
- runs-on: ubuntu-22.04
qt_major: 6
qt_qmake: qmake6
qt_packages: qmake6 qt6-base-dev libqt6core5compat6-dev
- runs-on: ubuntu-22.04
qt_major: 5
qt_qmake: qmake
qt_packages: qt5-qmake qtbase5-dev

name: Build (Linux, ${{ matrix.runs-on }}, Qt ${{ matrix.qt_major }})
runs-on: ${{ matrix.runs-on }}
steps:
- name: 'Install build dependencies'
run: |-
set -e
sudo apt-get update
sudo apt-get install --yes --no-install-recommends \
build-essential \
libapr1-dev \
libsvn-dev \
${{ matrix.qt_packages }} \
subversion
- name: 'Checkout Git branch'
uses: actions/checkout@v3
with:
submodules: true

- name: 'Configure'
env:
QMAKE: ${{ matrix.qt_qmake }}
run: |-
${QMAKE}
- name: 'Build'
run: |-
make
- name: 'Test'
run: |-
./test.sh --no-make
- name: 'Install'
run: |-
set -e
make INSTALL_ROOT="${PWD}"/ROOT install
find ROOT | sort
docker:
name: Check Dockerfile
runs-on: ubuntu-latest
steps:
- name: 'Checkout Git branch'
uses: actions/checkout@v3
with:
submodules: true

- name: 'Build'
run: |-
docker build .
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -2,4 +2,6 @@ Makefile
*~
*.o
svn-all-fast-export
svn-all-fast-export.exe
src/local-config.pri
/build/
12 changes: 12 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[submodule "test/libs/bats-core"]
path = test/libs/bats-core
url = https://github.com/bats-core/bats-core
[submodule "test/libs/bats-assert"]
path = test/libs/bats-assert
url = https://github.com/bats-core/bats-assert
[submodule "test/libs/bats-support"]
path = test/libs/bats-support
url = https://github.com/bats-core/bats-support
[submodule "test/libs/bats-file"]
path = test/libs/bats-file
url = https://github.com/tralston/bats-file
24 changes: 24 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
FROM ubuntu:22.04

# Change locale to let svn handle international characters
ENV LC_ALL C.UTF-8

# Install dependencies
RUN apt-get update && apt-get install --yes --no-install-recommends \
build-essential \
libapr1-dev \
libsvn-dev \
qt5-qmake \
qtbase5-dev \
git \
subversion \
&& rm -rf /var/lib/apt/lists/*

# Build the binary
RUN mkdir /usr/local/svn2git
ADD . /usr/local/svn2git
RUN cd /usr/local/svn2git && qmake && make

# Docker interface
WORKDIR /workdir
CMD /usr/local/svn2git/svn-all-fast-export
79 changes: 78 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -16,6 +16,15 @@ If you have a proper ruleset the tool will create the git repositories for you a

After it is done you likely want to run `git repack -a -d -f` to compress the pack file as it can get quite big.

Running as Docker image
-----------------------
Just mount your SVN folder, plus another working directory where Git repository will be created.
Sample usage with input mounted in /tmp and output produced in /workdir:
```
docker build -t svn2git .
docker run --rm -it -v `pwd`/workdir:/workdir -v /var/lib/svn/project1:/tmp/svn -v `pwd`/conf:/tmp/conf svn2git /usr/local/svn2git/svn-all-fast-export --identity-map /tmp/conf/project1.authors --rules /tmp/conf/project1.rules --add-metadata --svn-branches --debug-rules --svn-ignore --empty-dirs /tmp/svn/
```

Building the tool
-----------------
Run `qmake && make`. You get `./svn-all-fast-export`.
@@ -24,6 +33,19 @@ Run `qmake && make`. You get `./svn-all-fast-export`.
You will need to have some packages to compile it. For Ubuntu distros, use this command to install them all:
`sudo apt-get install build-essential subversion git qtchooser qt5-default libapr1 libapr1-dev libsvn-dev`

To run all tests you can simply call the `test.sh` script in the root directory.
This will run all [Bats](https://github.com/bats-core/bats-core) based tests
found in `.bats` files in the directory `test`. Running the script will automatically
execute `qmake` and `make` first to build the current code if necessary.
If you want to run tests without running make, you can give `--no-make` as first parameter.
If you want to only run a subset of the tests, you can specify the base-name of one
or multiple `.bats` files to only run these tests like `./test.sh command-line svn-ignore`.
If you want to investigate the temporary files generated during a test run,
you can set the environment variables `BATSLIB_TEMP_PRESERVE=1` or `BATSLIB_TEMP_PRESERVE_ON_FAILURE=1`.
So if for example some test in `svn-ignore.bats` failed, you can investigate the failed case like
`BATSLIB_TEMP_PRESERVE_ON_FAILURE=1 ./test.sh --no-make svn-ignore` and then look
in `build/tmp` to investigate the situation.

KDE
---
there is a repository kde-ruleset which has several example files and one file that should become the final ruleset for the whole of KDE called 'kde-rules-main'.
@@ -33,11 +55,66 @@ Write the Rules
You need to write a rules file that describes how to slice the Subversion history into Git repositories and branches. See https://techbase.kde.org/Projects/MoveToGit/UsingSvn2Git.
The rules are also documented in the 'samples' directory of the svn2git repository. Feel free to add more documentation here as well.

Rules
-----
### `create respository`

```
create repository REPOSITORY NAME
[PARAMETERS...]
end repository
```

`PARAMETERS` is any number of:

- `repository TARGET REPOSITORY` Creates a forwarding repository , which allows for redirecting to another repository, typically with some `prefix`.
- `prefix PREFIX` prefixes each file with `PREFIX`, allowing for merging repositories.
- `description DESCRIPTION TEXT` writes a `DESCRIPTION TEXT` to the `description` file in the repository

### `match`

```
match REGEX
[PARAMETERS...]
end match
```

Creates a rule that matches paths by `REGEX` and applies some `PARAMETERS` to them. Matching groups can be created, and the values used in the parameters.
You need to make sure the regex matching a SVN directory path matches also the end slash (e.g. `./`) otherwise Git fast-import will crash with an `fatal: Empty path component found in input` errors.
For example, the rule `/project/trunk/.*/myFolder`, should become `/project/trunk/.*/myFolder/`.



`PARAMETERS` is any number of:

- `repository TARGET REPOSITORY` determines the repository
- `branch BRANCH NAME` determines which branch this path will be placed in. Can also be used to make lightweight tags with `refs/tags/TAG NAME` although note that tags in SVN are not always a single commit, and will not be created correctly unless they are a single copy from somewhere else, with no further changes. See also `annotate true` to make them annotated tags.
- `[min|max] revision REVISION NUMBER` only match if revision is above/below the specified revision number
- `prefix PREFIX` prefixes each file with `PREFIX`, allowing for merging repositories. Same as when used in a `create repository` stanza.
- Note that this will create a separate commit for each prefix matched, even if they were in the same SVN revision.
- `substitute [repository|branch] s/PATTERN/REPLACEMENT/` performs a regex substitution on the repository or branch name. Useful when eliminating characters not supported in git branch names.
- `action ACTION` determines the action to take, from the below three:

- `export` I have no idea what this does
- `ignore` ignores this path
- `recurse` tells svn2git to ignore this path and continue searching its children.

- `annotated true` creates annotated tags instead of lightweight tags. You can see the commit log with `git tag -n`.

### `include FILENAME`

Include the contents of another rules file

### `declare VAR=VALUE`

Define variables that can be referenced later. `${VAR}` in any line will be replaced by `VALUE`.


Work flow
---------
Please feel free to fill this section in.

Some SVN tricks
---------------
You can access your newly rsynced SVN repo with commands like `svn ls file:///path/to/repo/trunk/KDE`.
A common issue is tracking when an item left playground for kdereview and then went from kdereview to its final destination. There is no straightforward way to do this. So the following command comes in handy: `svn log -v file:///path/to/repo/kde-svn/kde/trunk/kdereview | grep /trunk/kdereview/mplayerthumbs -A 5 -B 5` This will print all commits relevant to the package you are trying to track. You can also pipe the above command to head or tail to see the the first and last commit it was in that directory.
A common issue is tracking when an item left playground for kdereview and then went from kdereview to its final destination. There is no straightforward way to do this. So the following command comes in handy: `svn log -v file:///path/to/repo/kde-svn/kde/trunk/kdereview | grep /trunk/kdereview/mplayerthumbs -A 5 -B 5` This will print all commits relevant to the package you are trying to track. You can also pipe the above command to head or tail to see the first and last commit it was in that directory.
2 changes: 1 addition & 1 deletion samples/ignore-branch.rules
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ end repository

match /trunk/
repository myproject
branch master
branch main
end match

# Ignore this branch:
2 changes: 1 addition & 1 deletion samples/merged-branches-tags.rules
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ end repository

match /trunk/
repository myproject
branch master
branch main
end match

# Subversion doesn't understand the Git concept of tags
2 changes: 1 addition & 1 deletion samples/min-max-revision.rules
Original file line number Diff line number Diff line change
@@ -28,7 +28,7 @@ end match

match /trunk/
repository myproject
branch master
branch main
end match

match /branches/([^/]+)/
2 changes: 1 addition & 1 deletion samples/recurse.rules
Original file line number Diff line number Diff line change
@@ -15,7 +15,7 @@ end repository

match /trunk/([^/]+)/
repository \1
branch master
branch main
end match

#
2 changes: 1 addition & 1 deletion samples/standardlayout.rules
Original file line number Diff line number Diff line change
@@ -12,7 +12,7 @@ end repository

match /trunk/
repository myproject
branch master
branch main
end match

match /branches/([^/]+)/
4 changes: 2 additions & 2 deletions samples/two-projects.rules
Original file line number Diff line number Diff line change
@@ -15,12 +15,12 @@ end repository

match /project1/trunk/
repository project1
branch master
branch main
end match

match /project2/trunk/
repository project2
branch master
branch main
end match

# Note how we can use regexp to capture the repository name
16 changes: 10 additions & 6 deletions src/CommandLineParser.cpp
Original file line number Diff line number Diff line change
@@ -79,7 +79,7 @@ void CommandLineParser::Private::addDefinitions(const CommandLineOption * option
QString option = QString::fromLatin1(options[i].specification);
// options with optional params are written as "--option required[, optional]
if (option.indexOf(QLatin1Char(',')) >= 0 && ( option.indexOf(QLatin1Char('[')) < 0 || option.indexOf(QLatin1Char(']')) < 0) ) {
QStringList optionParts = option.split(QLatin1Char(','), QString::SkipEmptyParts);
QStringList optionParts = option.split(QLatin1Char(','), Qt::SkipEmptyParts);
if (optionParts.count() != 2) {
qWarning() << "WARN: option definition '" << option << "' is faulty; only one ',' allowed";
continue;
@@ -104,7 +104,7 @@ void CommandLineParser::Private::addDefinitions(const CommandLineOption * option
if(definition.name.isEmpty())
continue;
if (option.indexOf(QLatin1Char(' ')) > 0) {
QStringList optionParts = definition.name.split(QLatin1Char(' '), QString::SkipEmptyParts);
QStringList optionParts = definition.name.split(QLatin1Char(' '), Qt::SkipEmptyParts);
definition.name = optionParts[0];
bool first = true;
foreach (QString s, optionParts) {
@@ -137,7 +137,7 @@ void CommandLineParser::Private::setArgumentDefinition(const char *defs)
{
requiredArguments = 0;
argumentDefinition = QString::fromLatin1(defs);
QStringList optionParts = argumentDefinition.split(QLatin1Char(' '), QString::SkipEmptyParts);
QStringList optionParts = argumentDefinition.split(QLatin1Char(' '), Qt::SkipEmptyParts);
bool inArg = false;
foreach (QString s, optionParts) {
s = s.trimmed();
@@ -327,18 +327,22 @@ CommandLineParser::~CommandLineParser()

void CommandLineParser::usage(const QString &name, const QString &argumentDescription)
{
#if QT_VERSION >= 0x060000
QTextStream cout(stdout, QIODeviceBase::WriteOnly);
#else
QTextStream cout(stdout, QIODevice::WriteOnly);
#endif
cout << "Usage: " << d->argumentStrings[0];
if (! name.isEmpty())
cout << " " << name;
if (d->definitions.count())
cout << " [OPTION]";
if (! argumentDescription.isEmpty())
cout << " " << argumentDescription;
cout << endl << endl;
cout << Qt::endl << Qt::endl;

if (d->definitions.count() > 0)
cout << "Options:" << endl;
cout << "Options:" << Qt::endl;
int commandLength = 0;
foreach (Private::OptionDefinition definition, d->definitions)
commandLength = qMax(definition.name.length(), commandLength);
@@ -352,7 +356,7 @@ void CommandLineParser::usage(const QString &name, const QString &argumentDescri
cout << definition.name;
for (int i = definition.name.length(); i <= commandLength; i++)
cout << ' ';
cout << definition.comment <<endl;
cout << definition.comment << Qt::endl;
}
}

Loading