7

I often find myself puzzled with such a questioning. I need to version my projects for two reasons:

  • publish source code with its whole history so that people will be able to get into it, explore it and make use of it.
  • archive my project with its whole history so that I will be able to revert, fork again etc.

There are essentially two types of files in my projects:

  • essential files, raw-source-core, src/*, README.md, configure.ac, etc. I need them to be versioned for people.
  • files to help me working with the raw-source-core, like customCheckNBuildScripts/*, favoriteIDEConfiguration/*, absolutePaths/*, shortcuts/*, hooksILike/* etc. I need them to be versioned for me.

Which workflow would help me deal with such a conflict?

.gitignore provides a wonderful way of filtering between source files and build files. But I wish there would be two versions of it. In my ideal world, it would contain:

# RAW-SOURCE-CORE versioning part
# Dedicated to remote github git@github.com:user/myPublicRepo.git
*
!src/
!README.md
!configure.ac

# PERSONAL-USE-OF-THIS-SOURCE versioning part
# Dedicated to remote personal /media/user/flashdrive/myPrivateRepo
*
!src/
!README.md
!configure.ac
!customCheckNBuildScripts/
!favoriteIDEConfiguration/
!absolutePaths/
!shortcuts/
!hooksILike/

When I would push to github, only the first part would be used and get there.

When I would pull from github, I would only get the first category of files and the first part of .gitignore.

When I would push to personal, the second part would be used.

When I would pull from personal, I would get all my files.

Does this kind of hybrid versioning exist?

blunova
  • 388
  • 1
  • 4
  • 16
iago-lito
  • 183
  • 6
  • 5
    Isn't Git already complicated enough? – Robert Harvey Sep 11 '16 at 15:23
  • @RobertHarvey Come on, it is not ;) – iago-lito Sep 11 '16 at 15:34
  • 1
    How about having a separate repository containing only scripts, shortcuts, hooks etc. ? – Radu Murzea Sep 11 '16 at 18:23
  • @RaduMurzea it would need to be updated along manually.. but why not (easy to automate with a couple of aliases). In addition, private parts of `.gitignore` will be put on the public repo. This is not a big deal but I feel like it is the sign that this solution is still a workaround :) Well, it is an interesting workaround.. – iago-lito Sep 11 '16 at 18:34
  • Ignore files locally: https://stackoverflow.com/questions/1753070/git-ignore-files-only-locally. The drawback is that this is not directly under version control. – coredump Oct 02 '16 at 16:46

3 Answers3

7

You could consider a "root" repo containing your private tools/hooks/scripts, and a submodule for your public sources. The submodule would know nothing of the parent project and would have a "clean" history.

I should mention that I'm not really a fan of submodules, they are quite convoluted to work with IMO, but they would offer the separation you're looking for in this case.

axl
  • 1,237
  • 9
  • 11
0

.gitignore only helps you to be selective on commit. If you want different files pushed to different repositories, you need different commits, so probably separate branches.

You could keep only your sources on the master branch, and fork another branch master.personal from it, adding your support files on it. .gitignore on master would exclude your support files, but not on master.personal.

Commit the sources to master, merge master to master.personal and commit your support files there, then push each branch to it's repository.

You'll have to stash save your (unversioned) support files before switching branch, so adding an alias for the sequence of commands would probably be a good idea.

Philippe
  • 569
  • 2
  • 5
  • 1
    Interesting workaround.. Still, every branch in the project needs to be duplicated then. In addition, as you said, private parts of `.gitignore` will be put on the public repo (I know this is not a major issue, but in my opinion, this is the sign that this solution is.. still a workaround :) – iago-lito Sep 11 '16 at 18:30
  • Actually, `.gitignore` doesn't **need** to contain the private parts on the public repo. It's only a convenience to avoid adding support files on the public repo. – Philippe Sep 11 '16 at 19:09
0

If you are using GitHub or GitHub Enterprise, you could keep the public code in one project/repo, then fork that repo to a personal copy. In your personal copy, add all your personally versioned stuff, but try to keep the commits as either public or personal. This lets you track history of your personal stuff in git. When you want to share public stuff, you can create a pull request for public commits from your personal repo to the public one. Thus, the pull request boundary is a filter for your personal files. You could probably achieve this without GitHub (using just git), but it probably would involve a lot of complex sequences of git remote, git fetch, git apply, and git push. In the end, you would be writing scripts to duplicate what GitHub does for forked repos with pull requests. Keeping up to date with the parent/public repo is also not as automatic as git pull.

Greg
  • 406
  • 2
  • 4