2

I would like to copy a list of files from a given directory in a repository A to repository B with its commit history.

The internet is full with solutions for copying a full directory with all its content: Git: Copy history of file from one repository to another or https://mattsch.com/2015/06/19/move-directory-from-one-repository-to-another-preserving-history/

Those solution assumed I would like to copy all files in a subdirectory, which is not my case. I would like to copy a subset of files from a directory with its commit history from one repository to another.

For example: I would like to copy https://github.com/carla-simulator/scenario_runner/blob/master/srunner/examples/catalogs/EnvironmentCatalog.xosc to another repository B and to place it there at root (./).

The suggested solution from @jingx solved almost this problem.

Using

git am <the-patch-files>

the file will be placed in repository B at B/examples/catalogs/EnvironmentCatalog.xosc instead of B/EnvironmentCatalog.xosc

After moving the files to the "right" place, an additional commit is needed due to this directory change.

Unfortunately I was unable to do this using this method above.

How can I solve this problem?

Eagle
  • 3,362
  • 5
  • 34
  • 46
  • There is no such thing in Git as "file history": there are only commits. The history *is* the commits; the commits *are* the history. Add some commits to your repository and you have added more history. If you want multiple versions of a file, you'll want to add multiple commits; each commit will add to the history, and each commit that has the file in it, has the file in it. That is all there is, so that is all there is to do. – torek Dec 18 '20 at 18:38
  • In my question i speaks from a commit history and not from a "file history". – Eagle Dec 18 '20 at 18:46
  • I suspected that your wording implied that; but if you know that, then you already know the answer: figure out which commits, or parts of commits, you want, and turn those into new commits to add to your own repository. No matter how you choose to do it, it will be at least a little bit messy. – torek Dec 18 '20 at 18:54

1 Answers1

2

In principle you could do:

git format-patch --root -- file1 file2 etc.

Which will generate a series of *.patch files. Then in the new repo you would do:

git am <the-patch-files>

You might run into issues however if your repo has some complex history though, e.g. merges and file moves involving some of the files on your list.

Another solution would be to use git filter-history to rewrite the entire history, and essentially remove any files that you do not want to keep. You'd still need to deal with merges and file moves though.

[Edit] You can manipulate the target path, to some extent, to which a patch is applied by using -p and --directory with git am. For example, in the scenario you added, git am -p3 0001.patch would put file EnvironmentCatalog.xosc under the project root, and git am -p3 --directory alt 0001.patch would put it under alt/.

The big caveat here is of course that both the number you give to -p, and the path to --directory will vary from commit to commit. And it's not going to work if you have a commit with multiple files, each under different subdirectories at different levels.

jingx
  • 3,698
  • 3
  • 24
  • 40
  • grate answer. it tried it and the files where placed in repository B at the same path as in repository A. I would like to replace the file in a different directory. Is there way to deal with this? – Eagle Dec 18 '20 at 19:04
  • can probably simply edit the patches to replace the path with whatever you want instead. – underscore_d Dec 18 '20 at 19:05
  • @Eagle Not sure what you are referring to by "replace the file in a different directory". `git am` takes a `--directory` parameter which modifies the top level directory the file paths in the patches are related too. Is that what you are looking for? – jingx Dec 18 '20 at 19:42
  • @jingx assuming my files are in repository A and directory `a`, using your suggestion solution with the patch, i get in repository B directory `a` as well. Is there a way to "capture" one the file? – Eagle Dec 19 '20 at 05:41
  • @jingx, the problem with this nice solutions, that the old commits are there but on the "wrong" date. You see for e.g. commited 6 months ago, but in gitlab in the commits graph there are placed today. – Eagle Dec 19 '20 at 05:49
  • For the date problem, you can try add `--committer-date-is-author-date` to `git am`. But I'm sorry, I still don't quite get what you are trying to do with the directory. Could you edit your question to give an example? – jingx Dec 19 '20 at 15:43
  • I modified my question, I hope now it is understandable – Eagle Dec 20 '20 at 08:36