Ignore .git folder in sub folder

2020-08-12 16:22发布

Is it possible to add a sub folder with a .git folder to a repo, without Git treating it like a submodule? I've tried different methods to ignore that .git folder, but nothing this far has worked.

I have tried in /.gitignore:

/vendor/**/.git/

..and in /vendor/.gitignore:

.git/

The .git folder I want to ignore is in /vendor/foo/bar/.

标签: git
7条回答
混吃等死
2楼-- · 2020-08-12 16:29

Have you tried wildcards?

**/vendor/.git/
查看更多
家丑人穷心不美
3楼-- · 2020-08-12 16:36

You can do this by directly adding some (any) internal content first. Git detects submodules by encountering the .git entry when searching a newly-encountered directory, but if you give it an actual path to look for inside that directory it doesn't search.

So

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
查看更多
叛逆
4楼-- · 2020-08-12 16:37

Your question intrigued me so I tried it:

$ 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

As per your question, /tmp/foo is a Git repository. And with respect to /tmp/foo, /tmp/foo/bar is a subdirectory which itself has a .git directory.

As you can see, the parent foo repository totally ignored the bar/.git subdirectory and I didn't even need a .gitignore file.

And there's no way Git treats a path containing a .git folder as a submodule without having it registered in the .gitmodules file.

查看更多
乱世女痞
5楼-- · 2020-08-12 16:42

You can use git hooks to achieve what you want. Thinking out of the box, you could create a pre-commit hook that renames the .git directory of your included project, eg. to ".git2", add all files in the latter project except the ".git2" directory, commit all, push it and finally use post-commit hook to rename ".git2" folder back to ".git" in your module.

1) Create pre-commit file under .git/hooks/ of your root repo with contents:

#!/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) Create post-commit file under .git/hooks/ also with contents:

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

3) Change a file in your repo and finally:

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

My Original answer

查看更多
三岁会撩人
6楼-- · 2020-08-12 16:42

While it is true .git is automatically ignored, the main repo will treat /vendor/foo/bar as a gitlink (special entry in the main repo index), and not as regular files.

A trick would simply to move bar/.git outside the main repo:

  • vendor/foo/bar would be treated as a regular sub-folder, to be added to the main repo if need be.
  • the bar repo can at any time detect changes and make commit if you preceded your git command with GIT_DIR=/path/to/bar/.git git ...

For instance:

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
查看更多
仙女界的扛把子
7楼-- · 2020-08-12 16:42

As in jthill answer, you can add any item from subdirectory with .git and it will be treated as subdirectory instead of sub-module.

But if you already registered this subdirectory as sub-module that has .git you have to first remove that sub-module but leave it in your working tree - git rm --cached a/submodule.

More info on: How do I remove a submodule?

Then you can repeat steps from jthill answer.

From my research there is no way to stop treating .git folder as sub-module. So the best solution that I can think of right now is to have bash or any similar script that you can run in any folder in console. It should find any subfolders that have .git and attempt to add any file from that folder to the main .git, so it would stop treating them as sub-modules.

Source of code below: Bash script to automatically convert git submodules to regular files

#!/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

Remember to always commit/backup changes before trying new scripts to prevent any work/data loss.

查看更多
登录 后发表回答