手动蛮力方法:
对于登陆此页面的任何人,其目标只是将一堆 git 存储库存档在更大的父存储库或其他东西中,最简单的暴力解决方案是将所有嵌套的 .git 文件夹重命名为其他任何东西——例如:到..git。现在,git add -A 将像在父 git 项目中的任何其他普通文件夹一样添加它们,您可以轻松地在父 repo 中添加 git commit 一切。完成。
自动的蛮力方法:
使用git-disable-repos.sh
(https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles 的一部分)。
我刚刚在周末编写了这个脚本,并且已经在许多项目中使用了它。它工作得很好!有关详细信息和安装,请参阅文件顶部的 cmets,并运行 git disable-repos -h 以获取帮助菜单。
安装:
git clone https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles.git
cd eRCaGuy_dotfiles/useful_scripts
mkdir -p ~/bin
ln -si "${PWD}/git-disable-repos.sh" ~/bin/git-disable-repos
# If this is the first time using your ~/bin dir, log out and
# log back in now. Otherwise, just re-source your .bashrc file:
. ~/.bashrc
这是标准的使用模式:
cd path/to/parent/repo
# Do a dry-run to see which repos will be temporarily disabled
git disable-repos --true_dryrun
# Now actually disable them: disable all git repos in this dir and below
git disable-repos --true
# re-enable just the parent repo
mv ..git .git
# quit tracking the subrepo as a single file (required
# if you previously tried to add it to your main repo before
# disabling it as a git repo)
git rm --cached path/to/subrepo
# add all files, including the now-disabled sub-repos, to the parent repo
git add -A
# commit all files
git commit
这会将所有子存储库,包括它们的(现在 ..git).git 文件夹和所有 git 工件作为常规文件提交到父 git 存储库。您拥有 100% 的控制权!只想更新 1 个子存储库?然后 cd 进入它并将其一个 ..git 文件夹手动重命名为 .git,然后像正常一样使用该子存储库,然后在完成后再次运行 git disable-repos --true(或手动从 .git 重命名回到..git),并将其提交到父仓库。我的git disable-repos 脚本的美妙之处在于,它可以在必要时快速、无缝地一次性禁用或启用 100 个子存储库,而手动执行此操作是不切实际的。
也许我的用例很奇怪:我只需要将大量的东西提交到一个 repo 中,直到我可以在以后单独清理和分离每个 subrepo,但它可以满足我的需要。
这是git disable-repos -h的完整帮助菜单输出:
$ git disable-repos -h
'git disable-repos' version 0.3.0
- Rename all ".git" subdirectories in the current directory to "..git" to temporarily
"disable" them so that they can be easily added to a parent git repo as if they weren't
git repos themselves (".git" <--> "..git").
- Why? See my StackOverflow answer here: https://stackoverflow.com/a/62368415/4561887
- See also the "Long Description" below.
- NB: if your sub-repo's dir is already being tracked in your git repo, accidentally, stop
tracking it with this cmd: 'git rm --cached path/to/subrepo' in order to be able to
start tracking it again fully, as a normal directory, after disabling it as a sub-repo
with this script. To view all tracked files in your repo, use 'git ls-files'.
- References:
1. https://stackoverflow.com/questions/1274057/how-to-make-git-forget-about-a-file-that-was-tracked-but-is-now-in-gitignore/1274447#1274447
2. https://stackoverflow.com/questions/27403278/add-subproject-as-usual-folder-to-repository/27416839#27416839
3. https://stackoverflow.com/questions/8533202/list-files-in-local-git-repo/14406253#14406253
Usage: 'git disable-repos [positional_parameters]'
Positional Parameters:
'-h' OR '-?' = print this help menu, piped to the 'less' page viewer
'-v' OR '--version' = print the author and version
'--true' = Disable all repos by renaming all ".git" subdirectories --> "..git"
So, once you do 'git disable-repos --true' **from within the parent repo's root directory,**
you can then do 'mv ..git .git && git add -A' to re-enable the parent repo ONLY and
stage all files and folders to be added to it. Then, run 'git commit' to commit them.
Prior to running 'git disable-repos --true', git would not have allowed adding all
subdirectories since it won't normally let you add sub-repos to a repo, and it recognizes
sub-repos by the existence of their ".git" directories.
'--true_dryrun' = dry run of the above
'--false' = Re-enable all repos by renaming all "..git" subdirectories --> ".git"
'--false_dryrun' = dry run of the above
'--list' = list all ".git" and "..git" subdirectories
Common Usage Examples:
1. To rename all '.git' subdirectories to '..git' **except for** the one immediately in the current
directory, so as to not disable the parent repo's .git dir (assuming you are in the parent
repo's root dir when running this command), run this:
git disable-repos --true # disable all git repos in this dir and below
mv ..git .git # re-enable just the parent repo
Be sure to do a dry run first for safety, to ensure it will do what you expect:
git disable-repos --true_dryrun
2. To recursively list all git repos within a given folder, run this command from within the
folder of interest:
git disable-repos --list
3. Assuming you tried to add a sub-repo to your main git repo previously, BEFORE you deleted or
renamed the sub-repo's .git dir to disable the sub-repo, this is the process to disable
the sub-repo, remove it from your main repo's tracking index, and now re-add it to your
main repo as a regular directory, including all of its sub-files and things:
Description: remove sub-repo as a sub-repo, add it as a normal directory, and commit
all of its files to your main repo:
Minimum Set of Commands (just gets the job done without printing extra info.):
git disable-repos --true # disable all repos in this dir and below
mv ..git .git # re-enable just the main repo
# quit tracking the subrepo as a single file
git rm --cached path/to/subrepo
# start tracking the subrepo as a normal folder
git add -A
git commit
Full Set of Commands (let's you see more info. during the process):
git disable-repos --true # disable all repos in this dir and below
mv ..git .git # re-enable just the main repo
git ls-files path/to/subrepo # see what is currently tracked in the subrepo dir
# quit tracking the subrepo as a single file
git rm --cached path/to/subrepo
git status
# start tracking the subrepo as a normal folder
git add -A
git status
git commit
Long Description:
I want to archive a bunch of small git repos inside a single, larger repo, which I will back up on
GitHub until I have time to manually pull out each small, nested repo into its own stand-alone
GitHub repo. To do this, however, 'git' in the outer, parent repo must NOT KNOW that the inner
git repos are git repos! The easiest way to do this is to just rename all inner, nested '.git'
folders to anything else, such as to '..git', so that git won't recognize them as stand-alone
repositories, and so that it will just treat their contents like any other normal directory
and allow you to back it all up! Thus, this project is born. It will allow you to quickly
toggle the naming of any folder from '.git' to '..git', or vice versa. Hence the name of this
project: git-disable-repos.
See my answer here:
https://stackoverflow.com/questions/47008290/how-to-make-outer-repository-and-embedded-repository-work-as-common-standalone-r/62368415#62368415
This program is part of: https://github.com/ElectricRCAircraftGuy/eRCaGuy_dotfiles
其他更复杂的工具:
对于任何寻求更“专业”解决方案的人来说,这些似乎是最受欢迎的解决方案,排名靠前的是最受欢迎的(因此似乎也是最受支持的?):
-
git submodule - https://git-scm.com/docs/git-submodule - git 内置的规范的、官方支持的工具。
-
git subtree - https://www.atlassian.com/git/tutorials/git-subtree
-
git subrepo - https://github.com/ingydotnet/git-subrepo
其中哪一个是最好的?我不能说,但它们都让我感到困惑,所以我选择了我上面描述的手动蛮力选项,因为在这种情况下,它最符合我的预期目的,直到我有时间打破每个子-repos 有一天会变成他们自己在 GitHub 上单独维护的 repos。
更多关于git submodule:
2020 年 9 月 21 日更新:Martin Owen 在 2016 年 5 月 ("Git Submodules vs Git Subtrees") 撰写的这篇文章很好地比较了 git submodule 与 git subtree,并且普遍支持 git submodule。但是,当时作者连git subrepo都不知道,除了在cmets中提到过,也没有提过。
git submodule 似乎是 git 内置的规范的、官方支持的工具。虽然它看起来肯定有一个学习曲线,但我计划在我的下一个项目中使用它,现在我已经准备好打开该项目并再次开始工作,它取决于 sub-git repos。我计划从这里开始学习:
- Atlassian 的 Bitbucket 的简短介绍:https://www.atlassian.com/git/tutorials/git-submodule
- 官方
git submodule 文档在这里:https://git-scm.com/book/en/v2/Git-Tools-Submodules
其他参考资料:
- https://medium.com/@porteneuve/mastering-git-subtrees-943d29a798ec
- When to use git subtree?
- https://webmasters.stackexchange.com/questions/84378/how-can-i-create-a-git-repo-that-contains-several-other-git-repos
- Git treat nested git repos as regular file/folders
- Git: How to make outer repository and embedded repository work as common/standalone repository?
- https://www.atlassian.com/git/tutorials/git-subtree
关键字:git add subrepo; git 添加子存储库; git 添加嵌套存储库; git 添加.git 文件夹和文件