tags:

views:

331

answers:

5

I want to have files that I track in my local git repository that do not get checked in to the central svn repository when I run git-svn dcommit. I often have long-lived local-only changes to files tracked in the repository. Sometimes it's for debugging code. I also have project IDE files that I'd like to track. With plain old svn, I would just put those files into a changelist labelled "XYZ: DO NOT CHECK IN," and then just manually deal with the problem when I actually DO have changes that I need to commit.

Ideally, I would like to check my changes into my master branch but set something that prevents those specific changes from propagating to the svn repo. I would use git and git-svn in the conventional way, but certain commits never get pushed up. Obviously, I can do this manually every time I make a commit, but that's a pain.

I've considered and discarded a couple of things. I don't want to exclude these files, because sometimes I need to make changes that DO get dcommitted. Also, I'd like these files to appear in any local-only branches I create, like in the case of IDE files. However, I can't isolate these changes to a single branch because I will want them in every branch, as with the IDE files. It looks like something like guilt or stgit may do what I want, but it's not obvious, as they add their own layer of complexity on top of git, which I'm still learning.

A: 

You might want to consider using the stash for that.

git-stash - Stash the changes in a dirty working directory away

It might be underpowered for what you are describing though.

Kent Fredric
stash can only temporarily store uncommitted changes in the tree. Eventually the OP wants to check in the changes to the files, but prevent them from being committed to SVN repo.
Casey
Actually, some of the changes I might never want to commit. Maybe that's bad practice, but it's been convenient.
normal
+1  A: 

I am somewhat new to git, but I would recommend using a separate master and working branch in your local git repo.

Add your "non-SVN" files into the working branch only. Generally make all code changes in the working branch. When the "non-SVN" files change, add those using a unique commit, and set a commit message prefix (ie "local:" or "private:"). When you are ready to commit to SVN then:

  1. Show a log of commits to add to SVN:

    git co working
    git cherry master
    
  2. Add all upstream commits to the master branch, ignoring "private" commits. Repeat this step until all upstream commits are in master.

    git co master
    git cherry-pick <SHA1>
    
  3. Push commits to SVN repo:

    git svn rebase
    git svn dcommit
    
Casey
Thanks for the suggestion. I may have to fall back on that, but the drawback is I'll have to do extra work every time.
normal
A: 

I did some research and came up with a a possibility that could do it: 2 git repositories pointing at the same directory. The environment variable GIT_DIR stores the name of the local repository directory. If unset, git defaults to .git, but it could be anything.

What I could do then is have one repository in .git that maps to my Subversion repository. That's the common case. Then I could have another repository in .localgit. Each repository would have to be configured to ignore the files managed by the other one. That's easy with the ! for negating patterns.

When I make a change to local-only files that I want to check in, I either change my GIT_DIR environment variable or use the --git-dir command line argument. If I have my excludes/ignores set up properly, I won't have to worry about collisions. There's obviously some overhead to keep that up-to-date, but I can write a wrapper script that adds a file to the exclude of one repo when the file is added to the other. Also, that overhead only happens once per file rather than on every commit as with the multiple branch suggestion.

If I wanted to make it simpler, I could use naming convention, but I can also do it on each individual file, since the number of local-only files is almost certain to be in the single digits (otherwise I'm doing something wrong).

The one down side I see with this approach is that I wouldn't be able to branch and stash and reset local-only files the same way as the files in the SVN repository. My modifications to those are likely to be asynchronous with respect to my main edits, though, so I don't think it would be a significant problem in practice. I could also write wrappers for those functions that were multi-repository aware. Also, I will have to be more explicit when managing local-only files, but pretty much any situation would have to deal with that, short of multiple repositories being built into git itself.

normal
+2  A: 

My current solution to the problem is to use stacked git (stg) and maintain these local changes as separate patches. When I need to dcommit into Subversion, I do a

stg pop # naming the patches that should not be commited
stg commit # the rest of the patches to commit
git svn dcommit
stg push # naming the patches that are used locally

The nice thing about maintaining these as separate patches is that I can easily have patches that modify my unit tests to test different database backends. So normally I test against Oracle, but if I want to check against Derby, I do

stg push local-mods-derby
ant tests
stg pop

or if I want to test against PostgreSQL, I run

stg push local-mods-test-postgresql
ant tests
stg pop

Here, "local-mods-derby" and "local-mods-test-postgresql" are the patch names.

So maintaining separate patches of work is very easy with stg.

Blair Zajac
+1  A: 

Have you considered not working in the master branch?

If you keep your changes in a local git branch you can periodically merge or cherry-pick only the desired changes into your svn tracking branch. Switch over to the tracking branch, run your dcommit. Then go back to your local branch and rebase it.

If you want the changes in multiple branches, base them all off of the same branch point. Keep that branch as master+changes via rebasing. Then for all your other branches, just rebase off that base branch.

Ryan Graham