OMFG, do I really have to get back to SVN??? Part 2
In the first part of this post we started to use git to commit to/update from a SVN server, but we didn't touch one of the more interesting parts of Git: branching
Why would I want to use the git branching capabilities?
- because you can't create local branches in SVN
- because you can't commit locally in SVN
In this post we'll see how to work with SVN and Git branches.
NOTE: branches in Git are pointers to commits, branches in SVN are copies of files
first, let's create a branch in our SVN server:
$ svn copy trunk branches/my_new_svn_branch
A branches/my_new_svn_branch
$ svn commit -m "we've got a new svn branch"
Adding branches/my_new_svn_branch
Committed revision 8.
let's see our local and remote branches in Git
$ git branch -r //remote branches trunk // <---tracked by master local branch my_new_branch another_branch $ git branch -l //local branches * master // <-- tracking the trunk remote branch
now, let's update our git repository
$ git svn rebase //this command will only fetch changes to files
A branches/my_new_svn_branch/README
r8 = 635ea8cd541e29f12e86f439fb86787e6dc19f43 (git-svn)
First, rewinding head to replay your work on top of it...
Fast-forwarded master to refs/remotes/git-svn.
we must use the "fetch" command
$ git svn fetch (or rebase --all) //it'll fetch changes and detect svn branches Found possible branch point: https://svn_repo_url/trunk => https://svn_repo_url/branches/my_new_svn_branch Found branch parent: (my_new_svn_branch) 06a39b6e3b932b9fe5a7bfd0c7e4c57c9b14dee0 Following parent with do_switch M README Successfully followed parent r8 = 1a7df4c58fe71bb864cf6ecf5c67133ef5ecece4 (my_new_svn_branch)
at this point, if you look at the remote branches, you'll find the new svn branch (my_new_svn_branch)
$ git branch -r trunk my_new_branch another_branch my_new_svn_branch // <--- here is
ok, let's say we want to fix a bug in the my_new_svn_branch branch, so, we crate a new local branch (thanks Git):
$ git checkout -b bug_killer my_new_svn_branch
is that truth? yes, it is, let's see
$ git branch -l master *bug_killer // <-- here is
now, the bug_killer local branch is tracking the my_new_svn_branch remote branch
now we need to commit something
$ vim README //we modify the file $ git commit -m "modification 1" $ git checkout master //let's go to the master branch $ vim README //we modify the file in the master branch, why not? $ git commit -m "modification 2" $ git checkout bug_killer //get back to bug_killer branch $ vim YET_ANOTHER //we create a new file $ git add YET_ANOTHER $ git commit -m "I added a file"
at this point our bug_killer local branch is ahead of the my_new_svn_branch remote branch
and the master local branch is ahead of the trunk remote branch
so, we need to commit to the SVN server
$ git checkout bug_killer $ git svn rebase //update the my_new_svn_branch branch $ git svn dcommit //this will update the my_new_svn_branch directory $ git checkout master $ git svn rebase //update the trunk branch $ git svn dcommit //this will update the trunk directory $ git branch -d bug_fix //delete the bug_fix local branch, we don't need it anymore
and then we'll have three new commits in our SVN server
$ svn update
Creating a SVN branch through Git
well, I've created a branch in SVN through a SVN client and then we updated our Git repository and we got the new svn branch, but, what about create a svn branch through
$ git svn branch branch_name -m "commit message" Copying https://svn_repo_url/trunk at r19 to https://svn_repo_url/branches/branch_3... Found possible branch point: https://svn_repo_url/trunk => https://svn_repo_url/branches/branch_3, 19 Found branch parent: (branch_3) 06a39b6e3b932b9fe5a7bfd0c7e4c57c9b14dee0 Following parent with do_switch Successfully followed parent r26 = f27899a85d5328e3d038faf4b1e9f9eab2434fff (branch_3)
how another developer would see this?
$ svn update A branches/branch_3 A branches/branch_3/YET_ANOTHER A branches/branch_3/README Updated to revision 26.
very good!
OMFG, do I really have to get back to SVN??? Part 1
well, I'm not gonna do a Git vs SVN battle here, there are thousands of sites that say Git is better, easier, faster, so I don't need to repeat that, my point here is:
I have to use SVN after having using Git for several months and I don't want to get back to the SVN approach. what can I do?
well, Git has a beautiful SVN wrapper, here is how to use it:
Init
$ git svn init -s https://svn_repository_url your_dir
Initialized empty Git repository in your_dir
$ cd your_dir
$ git svn fetch
r1 = 6bdec5c6d7f42f7af9a905ea84ea7db60a364b70 (trunk)
A README
r2 = 7219311784935beded8254aa19d3f2635af4ec7a (trunk)
M README
r3 = 58136685ff4688df3106e7b30205ec862677436c (trunk)
Found possible branch point: https://svn_repository_url/trunk => https://svn_repository_url/branches/my_new_branch, 6
Found branch parent: (my_new_branch) 58136685ff4688df3106e7b30205ec862677436c
Following parent with do_switch
Successfully followed parent
r4 = 1221404c1cce31b94851f32f5ab3497f74998f03 (my_new_branch)
Found possible branch point: https://svn_repository_url/trunk => https://svn_repository_url/branches/another_branch, 6
Found branch parent: (another_branch) 58136685ff4688df3106e7b30205ec862677436c
Following parent with do_switch
Successfully followed parent
r5 = 611a1b5394afa69c6b669f58c0fc38629c2b4da0 (another_branch)
the -s option means that this repository has a standard layout, which means that it has at least 3 folders:
trunk #the main development folder
branches #a container folder for branches
tags #a container folder for tags
Clone (init and fetch in one step)
$ git svn clone -s https://svn_repository_url
At this moment you have one local branch: master
and 3 remote branches: trunk (for git, now this is a branch, not a simple folder), my_new_branch and another_branch
the git master branch is tracking the svn trunk branch, but we don't have local branches tracking any of the other 2 branches yet.
To keep update your working copy just perform:
$ git svn rebase //svn update
In order to keep updated your working copy must be clean, so if you have some changes you won't be able to commit, in such case use:
$ git stash
Saved working directory and index state WIP on master: 214231d a commit message
HEAD is now at 214231d a commit message
$ git svn rebase //let's suppose that we got conflicts
M README
Auto-merging README
CONFLICT (content): Merge conflict in README
Failed to merge in the changes.
$ git mergetool //solve conflicts
$ git rebase --continue
Applying: a commit message
$ git stash pop //you will recover your changes, but let's suppose again that we got conflicts too
Auto-merging README
CONFLICT (content): Merge conflict in README
$ git mergetool //solve conflicts
$ git commit -m "your commit message" //always, after solving a conflict we have to commit
[master 11a2588] your commit message
1 files changed, 1 insertions(+), 1 deletions(-)
I have to say that this is one of the worst scenarios while updating from an svn server, don't be scared about conflicts it's not that hard to solve them.
here is another example but now without conflicts
$ git stash
Saved working directory and index state WIP on master: 6a4131d another message
HEAD is now at 6a4131d another message
$ git svn rebase
$ git stash pop
$ git commit -m "your commit message"
[master 12c2a88] your commit message
1 files changed, 1 insertions(+), 1 deletions(-)
now, finally, to commit changes to the svn server
$ git svn dcommit //svn commit
Committing to https://svn_repository_url ...
M README
Committed r6
M README
r6 = 418ad2c0003c0d642a60ce889fd8931d174009a8 (git-svn)
No changes between current HEAD and refs/remotes/git-svn
Resetting to the latest refs/remotes/git-svn
trunk/README: locally modified
M README
Committed r7
M README
r7 = 731f821a38cc401737756470bed2a546e3e6554a (git-svn)
No changes between current HEAD and refs/remotes/git-svn
Resetting to the latest refs/remotes/git-svn
ok, but, what did just happen?
1. I made 2 git commits (to the local git repository)
2. In this way each commit made with git was "transformed" into a svn one.
3. so, we went from revision 5 to revision 7
then, if other developers using SVN want your changes, they would do:
$ svn update U trunk/README Updated to revision 7.
ok, but, what about all the git sexiness to work with branches and tags?
we will see it in the next part of this post...see you.