How can I use two SVN projects and corresponding git-svn branches with a single working directory?
I’m relatively new to Git, but I want to give it a try (vs SVN and Bazaar).
Can anyone recommend me a workflow for a situation similar to the following:
- Git Svn Migration - Handling directory of binaries
- How can I get git to read mode changes?
- How to clone a nonstandard svn repo to git?
- How do I tell git-svn about a remote branch created after I fetched the repo?
- Merge and push all git branches
- SVN to Git using a fast import/export stream
- 1 SVN repo, with several projects
- 1 working copy “src”
The ideea is that in “src” I need to checkout project A or sometimes project B. Both projects have several branches.
Then, I made a git repo in “src”, and
git remote add projA ..a_repo_git, “
git remote add projB ..b_repo_git“.
Now, I can see both of them from “src” using “git remote”, and I can see their branches with “git remote show projA”
And now the trouble..
- How can I get in “src” any of the branches in projA/projB ?
- How can I modify them, and then be able to push them back (first to the git_repos, or directly to the SVN repo)?
- Is this “workflow” ok, or do you have a better idea?
I did try in src:
git checkout --track -b work_branch projA branch_in_A
and after some fiddleing with “fetch” I managed to get the things. But then, I had problems pushing it back to the
a_repo_git, and then to SVN. It was mostly trial and error.
I have to admit, I still have problems with remote branches! (and I get lost when I have to use “
origin local_branch:origin_branch” or “
origin origin_branch:local_branch“, or “
origin origin_branch” or “
origin/origin_branch“! Back to the Git manual for some more reading.)
2 Solutions collect form web for “How can I use two SVN projects and corresponding git-svn branches with a single working directory?”
I haven’t updated the question, because in the last several days I was able to work really nice and easy with the help of my new repo 🙂
Here is what I did in the end:
Init two SVN repos in the same directory. (I can’t rember at this time, but it may be possible that a “git init” was done in the same dir, before:
mkdir src && cd src (not sure about this: git init) git svn init --stdlayout --prefix=projA/ -RprojA file:///path/to/svn/repo/A git svn init --stdlayout --prefix=projB/ -RprojB file:///path/to/svn/repo/B
The “–stdlayout” means that the SVN repos are in the standard format, with trunk, branches and tags on the same level.
The “–prefix” is used for the branches name. When we do “git branch -a”, all SVN branches from project A have the prefix “projA” (ex: projA/branch_name_of_A). The same thing is for B.
The -R option sets the name of the SVN repo, inside of the git repo (it’s the name we use with git when refering to the SVN repository/project)
The file:///path is the path to the SVN repo, and to the project inside the repo, in this case. I use “file://” because I used a flat-file repo, with no server. I am sure it work ok with http:// too, for a SVN server.
After this step, out of curiosity I had a look at the file src/.git/config. The two commands above created several “svn-remote” sections, one for each project (the -R option), and a generic one called “svn”. I’ve modified the entries, so there will be only references to the projects. Each reference had entries for the repo path (fetch) and for tags/branches/trunk. If you look at the file, you’ll understand what needs to be changed.
After this, I’ve fetched the contents of each project, using
git svn fetch projA #the contents of project A repo are downloaded git svn fetch projB #the contents of project B repo are downloaded
Now, runnig “git branch -a” displayed all branches from the two repos, and the master branch (local). “git branch -r” did not displayed any branches; probably because they are “svn-remote” and not “remote”
The current “master” branch was pointing to the trunk of the second project. I’ve decided to get rid of it, since it would cause problems when switching from a project to the other.
I’ve created two new branches to point to the trunks of each project, then removed the “master” branch:
git checkout -b master_project_A projA/trunk git checkout -b master_project_B projB/trunk git branch -D master
And now, for the “workflow”; to work on project A:
git checkout master_project_A #switch to project A git svn rebase #check for any updates on SVN repo git checkout -b work_on_A master_project_A #create a branch starting from the master of project A work work work on work_on_A; commit, etc git checkout master_project_A #go back to master of project A git svn rebase #check again for any update on SVN repo git checkout work_on_A #go back to the work branch git rebase master_project_A #update branch with any changes from the master of project A git checkout master_project_A #go back to the master of project A git merge work_on_A #merge to the master of project A the changes from the work branch git svn dcommit #commit changes to the SVN repo, in trunk, because master_project_A was pointing to its trunk
If I want to checkout an existing branch from the SVN, I can do it with:
git checkout -b work_on_branch projA/branch_name work work work git svn rebase #update any changes from projA/branch_name git svn dcommit #commit updates back to the branch in the SVN repo
For project B I can do the exact same things. In the end, I can have the contents of project A or B in the same dir “src”, and have access to both projects on the SVN repository from the same git repo! 😀
I still haven’t figure it out how to create a local branch then push it to the SVN repo – I was close, but it didn’t work.
Also, it may be useful to know the command “reset” (“git reset –hard projPrefix/branch”) but I broke a few things using it, so it may be better to leave this for some other time.
I hope this helps someone!
Let us first consider the simpler case of one remote repo and one local repo.
remote in the local repo works “only” as a reference to the other repo. You can use
fetch to retrieve the remote objects to your local store:
git remote add upstream git://... git fetch upstream
Now all branches from
upstream can be locally referenced and worked on by using
upstream/branchname. To really work on a remote branch, you should always make a local branch which tracks the remote branch:
git checkout -b new_local_branchname upstream/branchname
Now you can work locally and commit/merge as much as you like. As a final step you can
push you changes back into the central repository. The imporant bit is that AFAIK
push can only do fast-forward merges, that is upload the changes and set the new head. Therefore you have to prepare your local branch so that the local changes start on the tip of the remote branch. You can use
rebase to achieve that or avoid changing the central repository while you are working locally.
This describes the simple workflow between two repositories. Now to the specific case with SVN.
git svn complicates the picture by further constraining the kind of changes you can do. As with remotes, you should never directly modify the svn branches but always work on a local branch. Unlike remotes,
git svn always modifies commits as they go into the SVN repo to add the neccessary metadata. This last fact is probably the reason for many of your problems as commits on the SVN branch will always have different hashes from the original commits on your local branches.
Finally, your question about multiple projects in the same repo.
Git doesn’t support parallel checkouts of multiple branches in the same repo. You might want to look into submodules to integrate multiple repos.