一个目录中有两个 git 存储库?
一个目录下可以有2个git仓库吗? 我想不会,但我想我会问。 基本上,我想检查我的主目录配置文件(例如 .emacs),这些文件在我工作的所有计算机上应该是通用的,但有第二个本地文件存储库(例如 .emacs.local),其中包含机器特定的配置。 我能想到的唯一方法是将本地配置放在子目录中,并忽略主 git 存储库中的该子目录。 还有其他想法吗?
Is it possible to have 2 git repositories in one directory? I'd think not, but thought I'd ask. Basically, I'd like to check in my home directory config files (e.g. .emacs) which should be common across all of the machines I work on, but have a second repository for local files (e.g. .emacs.local), which contains machine-specific configurations. The only way I can think of to do that is to have the local config in a subdirectory and ignore that subdirectory from the main git repository. Any other ideas?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(12)
本文相对较好地介绍了这一点:
https://github.com/rrrene/gitscm-next/blob/master/app/views/blog/progit/2010-04-11-environment.markdown
基本上,如果您正在工作命令行这比您想象的要简单。 假设您想要 2 个 git 存储库:
您可以像这样设置它们:
您可以添加一个文件并将其提交到仅一个文件,如下所示:
所以 git 的选项首先出现,然后是命令,然后是 git 命令的选项。 您可以轻松地为 git 命令添加别名,例如:
这样您就可以用更少的输入来提交其中一个命令,例如
gitone commit -m "blah"
。似乎更棘手的是忽略。 由于 .gitignore 通常位于项目根目录中,因此您需要找到一种方法来切换它而不切换整个根目录。 或者,您可以使用 .git/info/exclude,但是您执行的所有忽略都不会被提交或推送 - 这可能会搞砸其他用户。 使用任一存储库的其他人可能会推送 .gitignore,这可能会导致冲突。 我不清楚解决这些问题的最佳方法。
如果您更喜欢 TortoiseGit 这样的 GUI 工具,您也会遇到一些挑战。 您可以编写一个小脚本,暂时将 .gitone 或 .gittwo 重命名为 .git,以便满足这些工具的假设。
避免 2 个存储库
您可以通过编写分支来实现类似的结果,尽管您仍然需要做一些舞蹈来让事情继续进行。
假设您有本地文件,例如原始问题中的系统特定设置。 您希望将它们排除在对其他开发人员的提交之外,但是,您希望将它们提交到某个地方,因为它们要么是运行所必需的,要么是调试中至关重要的,
而不是 2 个 git 存储库,您可以执行以下操作:
所以,您从本地更改开始,将其放在名为“本地”的分支上。 你永远不会将该分支推送到远程。
您将这些更改放在一边,然后从 main 中创建另一个分支,以您将要推送的内容命名,例如以您的名字命名(在我的例子中为“chris”)。
到目前为止,您已经有了两个不同的分支,但是您没有办法让它们一起工作。 您创建第三个组合分支 - dev,这里是 chris 和 local 的组合。
你在 dev 中进行开发,然后当需要推送时,你:
这会推送更改,在 chris 上清理,然后返回到 dev 并重新组合分支。 克里斯继续保持干净整洁,您有意义的更改被推动,并且您想要在本地保留的内容在本地分支上保持安全。
更特殊的场景:
推送本地分支
假设您想毕竟推送您的“本地”分支,例如,如果其中没有重要的秘密,并且您部分使用 git 作为备份。 修复很简单,只需将分支命名为长且非常清晰的名称,这样就没有开发人员拉动它并期望它为他们工作,例如 chris-local-settings。 如果您不喜欢一遍又一遍地输入长名称(并且制表符补全还不够),则对分支进行分支非常便宜:
生成的文件
假设您的本地分支更复杂,并且生成的文件不断造成混乱。 您需要它们进行调试,但您永远不想将它们推送到只包含您的非生成更改的干净分支。
您生成的文件可能遵循某种模式,或者如果不遵循某种模式,您可能对它们何时生成的位置有一定的发言权,因此它们确实遵循某种模式。 例如,如果您生成的所有文件都出现在名为“bin”的文件夹中,并且您刚刚完成了一些重要的编码:
因为您知道所有生成的文件都在 bin 文件夹中,所以您可以直接 cd 并 git add 在那里。 您可以将它们干净地转储到本地,然后返回到根目录并将其余部分提交到干净的分支。 然后你重构你的开发分支。
如果将来您需要知道给定日期和时间的构建是什么样子,您可以重构另一个分支,或者在 dev 分支上及时退回。 也就是说,我通常会在构建中经常丢弃并重新组合 dev 分支,因此,不幸的是,它没有历史记录:
想象一下 main 上发生了一些更改,我需要在可能毒害我的构建之前验证它们是否有效:
现在我要运行测试以验证构建。 如果他们表现不佳:
我会告诉最后推到主线的人,他们打破了它。 现在我在开发中安全了,远离了损坏的主分支。 或者,如果测试进展顺利:
这会将 dev 变成 chris 的干净合并,其中合并了 main 上的最新内容,因此那些拉动 chris 分支的人将获得 main 上的最新内容加上我的更改,仅此而已 - 这意味着我不是向他们抛出额外的合并冲突。 但这确实意味着我不断失去开发历史。
This article covers this relatively well:
https://github.com/rrrene/gitscm-next/blob/master/app/views/blog/progit/2010-04-11-environment.markdown
Basically if you're working from the command-line this is simpler than you might guess. Suppose you want 2 git repos:
You could set them up like so:
You could add a file and commit it to only one like so:
So the options for git come first, then the command, then the git command's options. You could easily enough alias a git command like:
So you can commit to one or the other with a bit less typing, like
gitone commit -m "blah"
.What appears to get trickier is ignores. Since .gitignore normally sits in the project root, you'd need to find a way to switch this as well without switching the entire root. Or, you could use .git/info/exclude, but all the ignores you perform then won't be committed or pushed - which could screw up other users. Others using either repo might push a .gitignore, which may cause conflicts. It's not clear to me the best way to resolve these issues.
If you prefer GUI tools like TortoiseGit you'd also have some challenges. You could write a small script that renames .gitone or .gittwo to .git temporarily so these tools' assumptions are met.
Avoiding 2 Repos
You can accomplish a similar result by composing your branch, although you're still doing a fair bit of dancing to keep things going.
Suppose you have local files, like system-specific settings in the original question. You want to keep them out of your commits to other developers, but, you want them committed somewhere, as they're either essential to run, or, could be critical in debugging
Instead of 2 git repos you can do the following:
So, you started with local changes, that you put out on a branch called "local". You're never going to push this branch to the remote.
You set those changes aside, then made another branch off of main named with what you'll be pushing, for example named after you (in my case, "chris").
So far you have the 2 distinct branches, but, you don't have a way for them to work together. You make a third, Composed Branch - dev here is a composition of chris and local.
You do your dev in dev, then when it's time to push, you:
This pushes the changes, clean out on chris, then comes back to dev and recomposes the branch. chris continues to remain squeaky clean, your meaningful changes are pushed, and the stuff you wanted to preserve locally stays safe on the local branch.
More special scenarios:
Pushing your local branch
Suppose you wanted to push your "local" branch afterall, for example if there's no important secrets in it and you're using git partly as a backup. Easy fix, just name the branch something long and very clear so no dev pulls it and expects it to work for them, like chris-local-settings. If you dislike typing that long name over and over (and tab completion isn't enough), branching the branch is super cheap:
Generated files
Suppose your local branch is more complex, and there are generated files that keep creating clutter. You need them to debug, but you never want to push them to your clean branch filled with just your, non-generated changes.
Your generated files probably follow a pattern, or if they don't, you probably have some say in where they generate when so they do follow a pattern. For example, if all you generated files appear in a folder named "bin" and you've just finished some important coding:
Because you know all your generated files are in the bin folder, you can just cd over and git add there. You cleanly dump them off in local, then back out to root and commit the rest to your clean branch. You then recompose your dev branch.
If in the future you need to know what your build looked like for a given day and time, you can recompose another branch, or, step back in time on the dev branch. That said, I usually throw out and recompose the dev branch often in my build, so, it has no history unfortunately:
Imagine some changes happened on main, and I need to verify they work before potentially poisoning my build:
Now I'd run tests to verify the build. If they go poorly:
And off I go to tell whoever last pushed to main, they broke it. Now I'm safe in dev away from the broken main branch. Or, if the tests go well:
That turns dev into a clean merge of chris, which has the latest on main merged in, so those pulling the chris branch get what's latest on main plus my changes and nothing more - meaning I'm not throwing extra merge conflicts at them. But it does mean I keep losing history on dev.
如果我理解您在做什么,您可以在一个存储库中处理所有内容,为每台计算机使用单独的分支,以及包含公共主目录配置文件的分支。
初始化存储库并向其提交公共文件,也许将 MASTER 分支重命名为 Common。 然后为您使用的每台计算机创建一个单独的分支,并将特定于计算机的文件提交到该分支中。 每当您更改公共文件时,请将公共分支合并到每个计算机分支中并推送到其他计算机(如果有很多,请为此编写一个脚本)。
然后在每台机器上,签出该机器的分支,其中还将包括通用配置文件。
If I understand what you're doing, you can handle it all in one repository, using separate branches for each machine, and a branch containing your common home directory config files.
Initialize the repo and commit the common files to it, perhaps renaming the MASTER branch as Common. Then create a separate branch from there for each machine that you work with, and commit machine-specific files into that branch. Any time that you change your common files, merge the common branch into each of the machine branches and push to your other machines (write a script for that if there are many).
Then on each machine, checkout that machine's branch, which will also include the common config files.
查看 git 子模块。
Have a look at git submodule.
RichiH 编写了一个名为 vcsh 的工具,该工具使用 git 的假裸存储库来管理点文件,以放置多个工作目录到 $HOME. AFAIK 与 csh 无关。
但是,如果您确实有多个目录,则 git-submodules 的替代方案(在最好的情况下这很痛苦,并且此示例用法不是最好的情况)是 gitslave ,它使从属存储库始终在分支的尖端签出,并且不需要三步过程来在附属存储库中进行更改(签出到正确的分支,进行并提交更改,然后进入超级项目并提交新的子模块提交)。
RichiH wrote a tool called vcsh which a tool to manage dotfiles using git's fake bare repos to put more than one working directory into $HOME. Nothing to do with csh AFAIK.
However, if you did have multiple directories, an alternative to git-submodules (which are a pain in the best of circumstances and this example usage is not the best of circumstances) is gitslave which leaves the slave repos checked out on the tip of a branch at all times and doesn't required the three step process to make a change in the subsidiary repo (checkout onto the correct branch, make & commit the change, then go into the superproject and commit the new submodule commit).
可以通过使用变量
GIT_DIR
来实现,但如果您不知道自己在做什么,则有很多注意事项。It is possible by using the variable
GIT_DIR
but has many caveats if you don't know what you are doing.我的首选方法是在子目录中使用存储库,并使用递归符号链接:
其中“repo/build”文件如下所示:
警告:不要使用“git add” .'
my preferred method is using a repo in a subdir, and use recursive symbolic links:
where the 'repo/build'-file looks like:
caution: dont use 'git add .'
是的,一个目录中可以有两个 git 存储库。
我假设一个远程存储库位于 GitHub 中,另一个位于 GitLab 中。 我还使用两个不同的 SSH 密钥来连接到这些远程存储库。
您可以在 GitHub / GitLab 之一中拥有两个远程存储库(并使用单个 SSH 密钥) - 不会有太大变化。
先决条件:
公共 SSH 密钥 (
id_ecdsa.pub
/id_rsa.pub
/id_ed25519.pub
等)存在于您的 GitHub 和 GitLab 配置文件中私钥 SSH 密钥(
id_ecdsa
/id_rsa
/id_ed25519
等)已添加并保留在操作系统的钥匙串中SSH 配置文件包含密钥为 GitHub 和 GitLab 指定:
这里是Chris 的回答模拟工作流程的细分 strong>:
初始化目录中的git:
git init
将 git 连接到一个远程存储库(位于 GitHub)
git Remote add origin [电子邮件受保护]:您的-用户名/your-repo.git
将
.git
重命名为.github
mv .git .github
再次初始化 git
git init
将git连接到另一个远程存储库(位于GitLab)
git Remote add origin [电子邮件受保护]:您的-用户名/your-repo.git
将
.git
重命名为.gitlab
mv .git .gitlab
验证当前目录是否连接到两个不同的远程存储库
git --git-dir=.github远程-v
git --git-dir=.gitlab远程-v
将文件添加到两个存储库
写入提交消息
推送到远程
我们在这里做的唯一额外的事情是使用
--git-dir
标志。如果您打算经常这样做,您可以在 shell 配置文件中添加一个别名(例如
.zprofile
、bashrc
等):未来的操作,例如
pull< /code>、
push
、add
、commit
可以像 -github pull origin main
、一样执行gitlab pull origin main
等Yes, it is possible to have two git repositories in one directory.
I'm assuming that one remote repository is in GitHub and the other in GitLab. I'm also using two different SSH keys to connect to these remote repositories.
You can have both remote repositories in one of GitHub / GitLab (and use a single SSH key) - not much would change.
Pre-requisites:
Public SSH keys (
id_ecdsa.pub
/id_rsa.pub
/id_ed25519.pub
, etc.) are present in your GitHub and GitLab profilesPrivate SSH keys (
id_ecdsa
/id_rsa
/id_ed25519
, etc.) are added and persisted in your OS's keychainSSH config file has keys specified for GitHub and GitLab:
Here's a break down of Chris's answer emulating a workflow:
Initialize git in a directory:
git init
Connect git to one remote repository (located in GitHub)
git remote add origin [email protected]:your-username/your-repo.git
Rename
.git
to something like.github
mv .git .github
Initialize git again
git init
Connect git to the other remote repository (located in GitLab)
git remote add origin [email protected]:your-username/your-repo.git
Rename
.git
to something like.gitlab
mv .git .gitlab
Verify that current directory is connected to two different remote repositories
git --git-dir=.github remote -v
git --git-dir=.gitlab remote -v
Pull remote (GitHub and GitLab) repositories
Add a file to both repositories
Write commit message
Push to remote
The only additional thing we're doing here is using the
--git-dir
flag.If you plan on doing this frequently you could add an alias in your shell config file (like
.zprofile
,bashrc
, etc.):Future operations like
pull
,push
,add
,commit
can be performed like -github pull origin main
,gitlab pull origin main
, etc.是的,子模块可能就是您想要的。 另一种选择是将工作副本放在子目录中,然后将符号链接从主目录指向感兴趣的文件。
Yeah, submodules are probably what you want. Another option would be to have your working copy in a subdirectory and then point symlinks from you home directory to the files of interest.
另一种选择是将它们放在单独的文件夹中,并创建从一个文件夹到另一个文件夹的符号硬链接。
例如,如果有存储库:
和:
您可以将文件夹
FolderA
和FolderB
从 Repo1 符号链接到 Repo2。 对于 Windows,在 Repo1 上运行的命令是:对于主存储库上的文件,您需要对每个文件进行符号链接,同时将它们添加到存储库
.gitignore
以避免噪音,除非您想要到它。The other option is to they on separate folders and create symbolic hard links from one folder to the other.
For example, if there are the repositories:
And:
You may symlink the folders
FolderA
andFolderB
from the Repo1 into the Repo2. For windows the command to run on the Repo1 would be:For the files on the main repositories you would need to symlink each one of them, also adding them to repository
.gitignore
to avoid noise, unless you want to it.OP 希望将多个存储库中的文件合并到单个目录中。
但是,如果您不想合并,而是需要在单个目录中的存储库之间切换:
现在您可以在目录之间切换,甚至可以在存储库之间挑选提交。
OP wants merging files from multiple repositories to single directory.
But if you do not want mering and instead need switching between repositories in single directory:
Now you can switch between directories and even cherry-pick commits between repositories.
免责声明:这不是广告。 我是所提供库的开发人员。
我创建了一个 git 扩展来处理您想要将多个存储库混合到一个文件夹中的情况。 该库的优点是跟踪存储库和文件冲突。 你可以在 github 上找到它。 还有 2 个示例存储库可供尝试。
Disclaimer: This is not advertising. I'm the developer of the provided library.
I've created a git extension to handle cases where you want to mix multiple repositories into one folder. The advantage of the lib is, to keep track of the repositories and file conflicts. you can find it on github. There are also 2 example repositories to try it out.
我看到了很多答案,但我有一个更简单的解决方案:
现在你在一个存储库中有两个 git!
在 gitgraken 中,你会看到这样的两个 git:
I see a lot of answers, but I have a simpler solution:
And now you have two gits in one repository!
In gitgraken you will see these two gits like this: