VCS comparison table

Linus Torvalds torvalds at
Sun Oct 22 18:12:00 BST 2006

On Sun, 22 Oct 2006, Tim Webster wrote:

> On 10/22/06, Linus Torvalds <torvalds at> wrote:
> > 
> > > project/file-1
> > > project/file-2
> > > project/.git-1
> > > project/.git-2
> > 
> > Ok, that's just insane.
> [snip]
> > Anyway. Git certainly allows you to do some really insane things. The
> > above is just the beginning - it's not even talking about alternate object
> > directories where you can share databases _partially_ between two
> > otherwise totally independent repositories etc.
> Perhaps this is insane, but it does not make sense to track all config
> files in etc as though they belong in a single repo.

Oh, ok, now I see what you're going after.

Right - if you track system directories in a repo, you'd quite possibly 
end up with multiple repositories. Although even then, I'd actually 
suggest that as a git user, you would only have one actual repository, and 
just multiple branches that have a disjoint set of files (again, it's 
certainly possible to have file overlap too, of course).

But the usage I would seriously suggest is to _not_ do development "inside 
/etc" itself. You'd have those git repositories somewhere else, say in 
"/usr/src/etc-repo" or similar, and then you'd have a few extra wrappers 
to help your particular usage. I have a few reasons for this:

 - I think being in /etc and doing development is just fundamentally scary 
   in itself, because if you do something wrong in the current directory, 
   you're just pretty badly off. It's better to have a "buffer zone" that 
   you do development in, and when you're happy, you do a "install" 
   command or something.

 - I think developing as "root" is totally broken, and some of the files 
   you are tracking may not even be _readable_ to normal users in their 
   real form, so you can't even do trivial things like "diff" as a normal 
   user otherwise. So again, the solution to this would be to do 
   development somewhere else, and have specific wrappers (with "sudo" as 
   appropriate, and your developer ID obviously specially in the sudo 
   files) to do those special "realdiff" and "install" commands.

 - finally: when you work with almost any SCM designed for source control, 
   you're almost inevitably going to have to have some "special" way to 
   track the things that source control usually does _not_ track because 
   it makes no sense for source code. So you'd have to have some special 
   file that tracks ownership/group/full permissions information, and 
   perhaps special devices (if you're tracking things like /dev).

   Again, the way to solve this would tend to be to have a few helper 
   scripts that use regular file-contents that _describe_ these things to 
   do "realdiff" and "install".

In other words, for at least three _totally_ different reasons, you really 
don't want to do tracking/development directly in /etc, but you want to 
have a buffer zone to do it. And once you have that, you might as well do 
_that_ as the repository, and just add a few specialty commands (let's 
call them "plugins" to make everybody happy) to do the special things.

And once you have that kind of setup, you're really better off with 
more of a "several branches for different kinds of files" or even totally 
different repositories. That's a detail, and I don't think anybody really 

Anyway, to make this slightly more grounded in examples, let me give a 
quick overview of what I'd do if I did this with git. Not a "real" setup 
at all, but kind of a "maybe something like this" - so don't get _too_ 
hung up about the details, ok? It's just a rough draft kind of thing.

First off, let's just say that I want to track /etc/group, /etc/passwd and 
/etc/shadow as one "thing". Whether that thing is a repository of its own 
or a branch in a bigger repository doesn't matter (right now I'm only 
doing those three), and quite frankly, I'm not going to even go into 
whether it _really_ makes sense to track "groups" and the passwd files 
together, but it's just an example, ok?

What I'd do is roughly:

	# set up the new repo (or branch, or..)
	mkdir identity-repo
	cd identity-repo
	git init-db

	# copy the data, set up a PERMISSIONS file to track extra info
	sudo cp /etc/group /etc/passwd /etc/shadow .
	sudo chown user:user *
	group root:root 0644
	passwd root:root 0644
	shadow root:root 0400
	git add .
	git commit -m "Initial setup"

and now I have the initial setup, together with permissions and user/group 
information on the things, all ready to track. I can do development in 
this as if it was a normal source-code repository.

So now I can do "work work work commit commit commit" as if these files 
were nothign special. What else do I need? I need the "plugins" to 
actually expose (install) my work, and perhaps to check that /etc matches 
what I expect (and nobody else did anything behind my back that I'd need 
to merge).

Let's call them "install" and "realdiff" as I did above, ok?

And again, I'm not going to even claim that the above two "plugins" are 
the right ones (maybe you want other operations too to interact with the 
"real" installed files), and I'm not going to really get all the details 
right, but here's kind of how you _might_ do it.

To create the script (let's make it shell, because that's what I'm used 
to, but it could be anything) "git-install" in your git binary directory, 
and make it do something like this:

	while read name chown chmod
		cp $name $name.tmp &&
		sudo chown $chown $name.tmp &&
		sudo chmod $chmod $name.tmp &&
		sudo mv $name.tmp /etc/$name

and make it executable.

Now, you can work in your git directory, and when you're happy, you can do

	git install

to actually copy it into the _real_ directory in /etc.

See? You can do something similar for "realdiff", that would compare the 
contents in /etc with what you have now in your development tree (where 
you want to script the thing to compare the PERMISSIONS file too).

And note: if you do the "plugin scripts" properly, they can work for _all_ 
your repositories that track different files in /etc. So you can work in 
many different repos, and track different files in each, and "git install" 
will do the right thing for each, regardless of the actual files you're 

Doesn't this sound like a workable situation? You get all the normal SCM 
tools (looking at history etc), and there's only a few special things you 
need to do when you actually want to install a specific version.

Btw: none of this is really "git-specific". The above tells you how to do 
local "git plugins", and it's obviously fairly trivial, but I suspect any 
SCM can be used in this manner.


More information about the bazaar mailing list