忽略子文件夹中的 .git 文件夹

17

有没有可能将一个带有.git文件夹的子文件夹添加到仓库中,而不使Git将其视为子模块?我已经尝试了各种方法来忽略那个.git文件夹,但到目前为止都没能奏效。

我已经在/.gitignore文件中尝试过:

/vendor/**/.git/

..并且在 /vendor/.gitignore 中:

.git/

我想要忽略的 .git 文件夹在 /vendor/foo/bar/ 下面。


2
.git/会被git自动忽略。 - Vinay Prajapati
你能澄清一下你想要什么吗?你确定不是你的 Git GUI 客户端错误地将一个带有 .git 目录的子文件夹视为子模块吗?你使用的是哪个 Git 客户端? - Gregory Pakosz
经过十二次谷歌搜索,Vinay Prajapati在评论中提供了我所寻找的答案。 - Matt Lemmon
7个回答

9
你可以通过直接添加一些(任何)内部内容来实现这一点。Git在搜索新遇到的目录时通过检测.git条目来检测子模块,但如果你给它一个实际的路径来在该目录中查找,它就不会搜索。
git add path/to/some/submodule/file     # bypass initial search that detects .git
git add path/to/some/submodule          # now git's index has it as ordinary dir

2
您可以使用git钩子来实现您想要的功能。可以创造一个pre-commit钩子,重命名您包含项目的.git目录,例如改为“.git2”,将后者项目中除“.git2”目录之外的所有文件添加到其中,提交所有更改,推送它,最后使用post-commit钩子将“.git2”文件夹重命名回您的模块中的“.git”文件夹。
1)在您的根repo下的.git/hooks/中创建pre-commit文件,并添加以下内容:
#!/bin/sh
mv "vendor/foo/bar/.git" "vendor/foo/bar/.git2"

git rm --cached vendor/foo/bar
git add vendor/foo/bar/*
git reset vendor/foo/bar/.git2

2) 在.git/hooks/下创建post-commit文件,内容如下:

#!/bin/sh
mv "vendor/foo/bar/.git2" "vendor/foo/bar/.git"

3) 在您的仓库中更改一个文件,最后:

git commit -a -m "Commit msg"
git push

My Original answer


谢谢你。这激发了一个基于哈士奇的解决方案。 - Xunnamius

0

你的问题引起了我的兴趣,所以我尝试了一下:

$ cd /tmp
$ git init foo
Initialized empty Git repository in /private/tmp/foo/.git/
$ cd foo
$ git init bar
Initialized empty Git repository in /private/tmp/foo/bar/.git/
$ cd bar
$ echo "this is bar" > bar.txt
$ git add bar.txt
$ git commit -m "initial commit"
[master (root-commit) c9d6507] initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 bar.txt
$ cd ..
$ pwd
/tmp/foo
$ git status
On branch master

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)

        bar/

nothing added to commit but untracked files present (use "git add" to track)
$ git add bar
$ git commit -m "parent initial commit"
[master (root-commit) b23e106] parent initial commit
 1 file changed, 1 insertion(+)
 create mode 100644 bar/bar.txt
$ echo "baz" > bar/.git/baz.txt
$ git status
On branch master
nothing to commit, working tree clean

根据您的问题,/tmp/foo 是一个Git仓库。关于 /tmp/foo/tmp/foo/bar 是一个子目录,它本身有一个 .git 目录。
可以看到,父级 foo 仓库完全忽略了 bar/.git 子目录,我甚至不需要一个 .gitignore 文件。
而且没有办法让Git将包含 .git 文件夹的路径视为子模块,除非在 .gitmodules 文件中注册它。

我本可以将其作为评论,但我无法详细阐述我得出结论的确切步骤。因此,我将其作为答案呈现。 - Gregory Pakosz
你的记录与我所期望的和 Git 文档不符,而且我自己也无法复现。您在运行此操作时使用的 Git 版本是哪个?到目前为止,我已经尝试了 2.16、2.12 和 2.10。 - jthill
在 MacOS 上的 git 版本为 2.16.2。 - Gregory Pakosz
我可以在Linux上使用2.16.2重现它。 - Gregory Pakosz

0

jthill answer所述,您可以添加任何带有.git的子目录中的项目,并将其视为子目录而不是子模块。

但是,如果您已将此子目录注册为具有.git的子模块,则必须首先删除该子模块,但将其保留在您的工作树中-git rm --cached a/submodule

更多信息:如何删除子模块?

然后,您可以重复jthill answer中的步骤。

从我的研究中得知,没有办法停止将.git文件夹视为子模块。因此,我现在能想到的最好的解决方案是拥有一个bash或任何类似的脚本,您可以在控制台中的任何文件夹中运行它。它应该查找任何具有.git的子文件夹,并尝试将该文件夹中的任何文件添加到主.git中,以便停止将它们视为子模块。

以下是代码来源:自动将Git子模块转换为普通文件的Bash脚本

#!/bin/bash

# Get a list of all the submodules
submodules=($(git config --file .gitmodules --get-regexp path | awk '{ print $2 }'))

# Loop over submodules and convert to regular files
for submodule in "${submodules[@]}"
do  
   echo "Removing $submodule"
   git rm --cached $submodule # Delete references to submodule HEAD
   rm -rf $submodule/.git* # Remove submodule .git references to prevent confusion from main repo
   git add $submodule # Add the left over files from the submodule to the main repo
   git commit -m "Converting submodule $submodule to regular files" # Commit the new regular files!
done

# Finally remove the submodule mapping
git rm.gitmodules

记得在尝试新脚本之前,始终提交/备份更改以防止任何工作/数据丢失。


0

虽然 .git 会自动被忽略,但主仓库将把 /vendor/foo/bar 视为 gitlink(主仓库索引中的特殊条目),而不是普通文件。

一个技巧就是将 bar/.git 移出 主仓库:

  • vendor/foo/bar 将被视为常规子文件夹,如果需要,可以添加到主仓库中。
  • 如果在 git 命令之前加上 GIT_DIR=/path/to/bar/.git git ...,则 bar 仓库随时可以检测更改并进行提交。

例如:

cd /path/to/main/repo/vendor/foo/bar
GIT_DIR=/path/to/bar/.git git status
GIT_DIR=/path/to/bar/.git git add .
GIT_DIR=/path/to/bar/.git git commit -m "changes to bar"
GIT_DIR=/path/to/bar/.git git push

备选语法:git --git-dir=/path/to/bar/.git status - VonC

0

你可以使用 Git 排除文件来实现这个功能。

首先,创建一个 .gitexclude 文件:

$ echo "vendor/*/.git" >> .gitexclude

然后将此文件添加到您的Git配置中,作为排除源:

$ git config core.excludesFile .gitexclude

现在你可以添加文件而Git不会提示你将它们作为子模块添加:
$ git add vendor
$

您可以使用 git check-ignore 命令来验证 Git 中的文件是否确实是“隐藏”的:

$ git check-ignore vendor/foo/.git
vendor/foo/.git
$ git check-ignore vendor/foo/bar.txt
$

参考: man git-add(1) man git-check-ignore(1)


-1

你试过通配符吗?

**/vendor/.git/

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接