12

I have a top level git repo organized like so:

  • .git/
  • repoA/
    • .git/
    • file
    • file2
    • folder/
    • ...
  • file
  • file2
  • folder/
  • ...

How can I get git to add and commit repoA (and repoA/.git) as if they were regular files/folders?

Specifically, I want to bypass the treatment of such a folder as a submodule but I want to retain the branches/history of the nested repo (so the .git folder is required).

I do not want to alter the state of the nested repo (by committing or merging histories) and do not want to push it to a separate repo on the remote.

The intended result is the same as if I were to tar repoA and un-tar it later. That is, all the files are intact with no modification or special treatment by git.

2

2 Answers 2

11
+100

This is not directly possible. The .git directory has a special meaning for git. When you run git operations from inside a git work-tree (not necessarily from the top level) without explicitly specifying the path to the repository (via the --git-dir option or the GIT_DIR environment variable) the latter is automatically discovered by looking for the first ancestor directory that contains a .git subdirectory. A .git directory that is intended to be considered as regular content would interfere with that procedure.

However, I can suggest the following workaround:

  1. In your sub-repository, rename the .git directory to something else (e.g. .git.subrepo, .pseudogit, etc):
mv repoA/.git repoA/.pseudogit 
  1. Add and commit the sub-repository directory:
git add repoA git commit -m "Added repoA as regular sub-directory" 

After this git operations from inside the sub-repository tree will work using the master repository by default. When you need to study the history of the sub-repository you will have to use the --git-dir option:

cd repoA git --git-dir .pseudogit log 
Sign up to request clarification or add additional context in comments.

1 Comment

Add can add a alias like this alias gitsub="git --git-dir .pseudogit", so you can do gitsub log, gitsub status commands without specicy the param.
5

You can look into git subtree.

For that, if you currently have submodules, you can follow "Convert a git repository from submodules to subtrees":

cat .gitmodules |while read i do if [[ $i == \[submodule* ]]; then mpath=$(echo $i | cut -d\" -f2) read i; read i; murl=$(echo $i|cut -d\ -f3) mcommit=`eval "git submodule status ${mpath} |cut -d\ -f2"` mname=$(basename $mpath) echo -e "$name\t$mpath\t$murl\t$mcommit" git submodule deinit $mpath git rm -r --cached $mpath rm -rf $mpath git remote add $mname $murl git fetch $mname git branch _$mname $mcommit git read-tree --prefix=$mpath/ -u _$mname fi done git rm .gitmodules 

(test it on a copy of your repo first)

See also "When to use git subtree?", which differs from ingydotnet/git-subrepo.

5 Comments

Your first link is now this: atlassian.com/git/tutorials/git-subtree. It auto-forwards so no big deal. Looks like a pretty good article. I'm reading it now.
And yet another option: github.com/ingydotnet/git-subrepo
@GabrielStaples Thank you . I have updated the answer accordingly.
Glad to help. I just wrote this git disable-repos tool over the weekend too to archive a bunch of old projects (into a single parent repo) which need fixing up and reviving at a later date: stackoverflow.com/a/62368415/4561887. Perhaps your or someone else will find it useful as well.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.