I am versioning my config files with git. Now I need to move some of my config files to a different repository, to achieve a clean structure. Is there a way I can keep the change log for a file if I move it to a different repository?

I would like to have all commits of repo A in repo B that touched file A/a if I move it to B/a. Ideally, if I afterwards move A/x to B/x, I would want to see B/a and B/x appear together in commits that touched both files in repository A. I would not expect to have any development step of A/a merged into any of the commits of B, I just want them to appear there afterwards.

Thank you, best regards

link|improve this question
How do you want this to appear? Git does not keep changelogs for individual files, only for entire repositories. Do you want the file to be added to past commits? Do you want an entirely separate line of development containing just these config files to get merged into master? – Stephen Jennings Jul 16 '10 at 15:04
Also, which operating system are you using? – Stephen Jennings Jul 16 '10 at 15:06
I hope the second paragraph I added to the initial question clarifies my idea. The repositories are located on various linux distributions (I added that tag). – exic Jul 16 '10 at 17:45
+1 because this was an interesting question to (hopefully) solve – Stephen Jennings Jul 17 '10 at 6:58
feedback

2 Answers

up vote 3 down vote accepted

Assume you want to transfer the history of filename.conf from one source repository to another receiving repository. I think the strategy you want to follow is:

  1. In the source repository, create a branch of commits which are re-written to contain only filename.conf.
  2. Fetch the commits into the receiving repository.
  3. Merge the independent line of commits into a normal branch in the receiving repository.

Definitely make backups of your repositories before you do any of this!

In the source repository:

git checkout -b filtered-commits
git filter-branch -f --prune-empty --tree-filter 'find . -not -name filename.conf -exec rm {} \;' filtered-commits

Then, in the receiving repository:

git remote add source path/to/source/repo
git fetch source filtered-commits
GIT_INDEX_FILE=.git/tmp-index git read-tree FETCH_HEAD
GIT_INDEX_FILE=.git/tmp-index git checkout-index -a -u
git update-index --add -- filename.conf
cp .git/FETCH_HEAD .git/MERGE_HEAD
git commit

The second part is basically stolen from something Linus figured out how to do in 2005, and the first part is normal use of git filter-branch.

If you also need to move the path that filename.conf is in within the repository, you'll probably need to use the --subdirectory-filter option on git filter-branch.

link|improve this answer
It really seems to be working. Someone should make a script out of this, catch all things that can go wrong and make it available to the whole git community :-) – exic Jul 27 '10 at 14:20
Yet the filter-branch command is missing an option to keep the history of filename.conf if it was moved/renamed at some point of its lifetime. (edit: no <pre> or <code> here...) – exic Jul 28 '10 at 15:23
feedback

I was thinking about something like this for Mercurial the other day. I think I'd write a script (probably python, but really anything that can run shell commands) to:

  1. For each revision that touched File X (call it "#rev")
    1. Copy File X from #rev to its new location
    2. Commit in the new repo with the message from #rev

It would be nice if the script could allow comment-editing and "forgetting" of some versions, where desired.

link|improve this answer
It also should keep date and author, I guess this script would get quite big.. maybe I'll find a way to merge single files into a new directory, hrm... anyway, thanks for your input! – exic Jul 16 '10 at 14:51
feedback

Your Answer

 
or
required, but never shown

Not the answer you're looking for? Browse other questions tagged or ask your own question.