Git - Include files from other repositories

2019-03-23 09:14发布

问题:

With Git, I'd like to include some common JS/CSS library and/or utility methods (i.e. specific files from another repo) in my project, and I'd like it so they're always up-to-date. I don't really want the entire remote repository(s). Bonus if I can work on my "local copies" of the remote files and push the changes back up.

A somewhat parallel example: in ASP.NET, I would do this by referencing the ("remote") other libraries' .dll files (without "copy local"), so that whenever I recompile the external libraries my project would already point to the newest versions.

Example Scenario

My project is...MyProject, and I just want a couple files from external repositories ExternalLibrary and External2. I'd prefer not to clone each repository somewhere else and copy-paste the files into my repo. If I make an improvement to MyProject/scripts/common1.js, I'd like to push that back to ExternalLibrary.

  1. MyProject/
    • index.html
    • scripts/
      • mycode.js
      • otherplugin.js
      • common1.js <-- from ExternalLibrary
      • plugin2.js <-- from ExternalLibrary
    • styles/
      • mystyle.css
      • common.css <-- from External2
  2. ExternalLibrary/
    • common1.js
    • plugin1.js
    • plugin2.js
    • bunchofothercrap...
  3. External2/
    • common.css
    • bunchofothercrap...

Related references:

  • Git: how to work with multiple repositories?
  • How to checkout only one file from git repository?
  • Get file from other developer local GIT and add to main repository
  • Can a git repository be created where branches are clones from other repositories?
  • http://www.kernel.org/pub/software/scm/git/docs/gitworkflows.html

回答1:

Git does not have any support for picking out select files in a remote project. You could pick out the files you want with subtree and then figure out some sort of strategy for getting it back in, but that usually is way to complicated, especially if you suddenly decide you want a couple more files than you originally picked.

What I usually end up doing is using symlinks. This can be done by adding the projects as submodules in your project, then symlinking the files into the right location.

Your example would go something like this:

$ git clone <url> myproject
$ cd myproject
$ git submodule add <url> external_library
$ git submodule add <url> external2
$ cd scripts
$ ln -s ../external_library/common1.js
$ ln -s ../external_library/plugin2.js
$ cd ../styles
$ ln -s ../external2/common.css

To get symlinks to work in windows:

  • If you are a member of the Administrators group you have to turn off User Access Control (UAC) and then restart the computer.
  • If you are not an administrator you need to get the SeCreateSymbolicLinkPrivilege privilege

Then before you make any changes I would go and create a new branch:

$ cd external_library
$ git checkout -b myproject
# make changes back in ../myproject
$ git commit <files> # in external_library

Then you can push your branch to github or something and submit a pull request to the author in order to contribute your changes back.

You can stay up to sync like this:

$ cd external_library
$ git checkout master
$ git pull
$ git checkout myproject
$ git merge master

You also need to update the parent project when the submodule changes (e.g. git commit external_library). Anyone using your project would need to do a git clone --recursive <url_to_myproject>.

NOTE: You can achieve most of this without using a separate branch for your project. Use whatever makes most sense to you.