Showing posts with label git. Show all posts
Showing posts with label git. Show all posts

Monday, August 13, 2018

Migration from SVN to GIT

Step 0 : Define migration strategy



Option 1 [recommended] : If possible, do not bother to migrate the SVN history to git but rather keep the old repositories archived and start over in git from the tip of the trunk.

Option 2 : Migrate trunk and tags only.

Option 3 [can be complex] : Migrate the entire repository.

I picked option 3 because my colleagues wanted to keep all of the history. IMO this is not necessary as long as the old repositories are still accessible. Plus, the migrated history is not perfectly identical to SVN and can be more confusing than helpful.


Step 1 : Create a file with authors


We should convert authors' svn identifiers to git format (Firstname Name <mail>).
To do this, run the following command from your SVN repo

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors.txt


Now edit the file and fill the missing information to finally have something like that:

MMO = Mickey Mouse <mickey.mouse@disney.com>
DDU = Donald Duck <donald.duck@disney.com>

Step 2 : Migrate dependencies first


If your main project is using externals, those will need to be converted to submodules (other options are possible like subtree or third party git externals but in most cases, submodule will do just fine).

To do that, repeat the following commands for each dependency repository:

git svn clone --trunk=<trunk_dir> --branches=<branches_subdir> --tags=<tags_subdir> --no-metadata --authors-file=authors.txt <svn_repo_url> .


Note: if the svn repository follows the standard 'trunk,branches,tags' structure, replace '--trunk=<trunk_dir> --branches=<branches_subdir> --tags=<tags_subdir>' with --stdlayout

Now export the branch list to a file.

git branch -r > branches.txt


Filter the list of branches in branches.txt and keep only those you want to migrate.
Copy tags to a separate file for now (tags.txt).

Now for each entry in branches.txt, do:

git checkout -b <local_branch_name> <remote_branch_name>


Use the branch name in branches.txt for <remote_branch_name>.

For each tag, do the following:

git checkout -b <local_branch_name> <remote_branch_name>
git tag <local_branch_name>
git checkout master
git branch -D <local_branch_name> 

Tags are exported as branches by git-svn so we are forcing a checkout and we manually add the tag in git repository.

Now run the following command to clean history from empty commits (migration side-effect):

git filter-branch --prune-empty -f -- --all


Delete trunk branch

git branch -D trunk


Configure remote git repository

Here I suppose that you already have created a remote git repository to host your code.

git remote add origin <git_remote_repo_url>


Finally push the repo

git push origin --mirror


Step 3 : Migrate the main project repository


Repeat steps from Step 2 until trunk deletion.
From there, we will need to resolve externals.

We will start with master branch, but these steps need to be repeated for each branch.

git checkout master


Run the following command to export the list of externals to a file.

git svn show-externals --id=origin/trunk > externals.txt


Note: In my case, this command wouldn't work for other branches and it is particularily slow. I managed to achieve the same thing from svn command line in the old repository, for each branch.

svn propget svn:externals -R <externals_dir> > externals.txt


Suppose our svn:externals were in a folder named Externals, here is what should be done for each submodule:

git submodule add --force <dependency_git_remote_repo_url> ./Externals/<submodule_dir>


Then we need to fix the submodule to the commit that matches the version used in svn.

cd ./Externals/<submodule_dir>


For tags:
git checkout <commit_id_or_tag_label>


For branches:
git checkout -b <local_name> <remote_git_branch_name>


cd ../..


Repeat these steps for all submodules. Once done, commit:

git commit -m "Migrated svn:externals properties to .gitmodules"


Repeat these steps for all branches. Before starting, for each branch, do cleanup to avoid confusing error messages:

rm -rf ./Externals


Finally, when all branches have been processed, push the repository to remote server:

git remote add origin <git_remote_repo_url>

git push origin --mirror

Tuesday, April 30, 2013

Git tutorial

Git is a distributed version control system which means that it does not require a central server to store all the data, unlike SVN or CVS. In practice, there is usually a central repository (remote repository, typically hosted on the internet) that one can copy (cloning). When cloning an existing repository , the user grabs the whole working tree. If you'd like to create a branch for instance to work on a specific part of your code in parallel, the branch will be local. The central copy does not need to have a counterpart.

Linux kernel's project is using git as its version control system. Some of the following commands may be useful :

Create a Git repository

# Run it in your development directory
git init
This folder will then contain a .git directory containing the complete history of the repository and .git/config will store the local configuration for it.

Add files to the repository

# Replace . by the file name if you're not planning to add all files
git add .
The marked files have been added to the staging area. It means that they will be part of the next commit. All of your modified files need to be staged (added) so that they will be included in the next commit.

Check repository status

git status
You will see which files have been modified, which ones are staged and which are not, conflicts, etc...

Commit files to the repository

git commit -m "Commit message"

Trace back your modifications

git log
You will see the list of your commits and your activity in your working tree.

Move / Rename a file

git mv <orignial file path> <new file path>

Remove a file from repository

git rm <file name>
Note : you can also simply delete the file manually. In this case, you have to add the '-a' option to the commit command to take the deletion into account.

Remove a file from staging area

git reset <file name>

Working with Remote Repositories

Ok, now we got the basics, how do we synchronize our work with others ? In the example above, we started from scratch, and our repository is local. What if somebody would like to copy it ?

Clone a remote repository

Imagine that we created a repo in a folder named "original_repo". Let's move back and create a new folder :
cd ..
mkdir clone_repo
cd clone_repo
Once we're here, we will clone the "original_repo" into "clone_repo" :
git clone ../original_repo.git .
Note : A git repository address always end with a ".git" extension.
Note 2 : If you omit the '.' at the end of the command, git will create a directory named like the origin (here 'original_repo'), move into it and pull the files from there.

If the git repository is hosted on the web, it is almost the same :
git clone https://linux389pi@bitbucket.org/linux389pi/linux389pi.git

Push changes to a remote repository


You probably noticed that git commit does not mirror your modifications on the remote repository. Instead, it creates a local commit object (snapshot). To send your modification to the central repository, you will have to push your local repository:
git push

Pull changes from the remote repository

The opposite action of pushing is pulling. You will synchronize your repository with the central one by pulling :
git pull

If you are looking for more information about git, check this link :

Git - Book 

If you are also willing to experiment git with a very cool tutorial, here is the link :

Git in practice 

 
biz.