首页 > 解决方案 > 尝试更正我的 GitHub 子模块以将其删除并添加到根文件夹以进行提交

问题描述

我正在尝试设置我的 git 根文件夹,以便在git add .git commit -m "a simple message"git push. 问题是我以某种方式将我的 gatsby 文件夹变成了一个子模块,我似乎无法删除它并恢复到 gatsby 文件夹,它只是需要提交的根文件夹的一部分。这是我最近的终端活动:

ericphifer@Erics-MacBook-Pro WestWater % git add .
ericphifer@Erics-MacBook-Pro WestWater % git commit -m "update files and folders to align between github and vscode"
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)
        modified:   gatsby-ww (modified content, untracked content)

no changes added to commit (use "git add" and/or "git commit -a")
ericphifer@Erics-MacBook-Pro WestWater % mv WestWater westwaterco
mv: rename WestWater to westwaterco: No such file or directory
ericphifer@Erics-MacBook-Pro WestWater % git rev-parse --show-toplevel #print repo top-level directory
/Users/ericphifer/Desktop/WestWater
#print
fatal: ambiguous argument '#print': unknown revision or path not in the working tree.
Use '--' to separate paths from revisions, like this:
'git <command> [<revision>...] -- [<file>...]'
ericphifer@Erics-MacBook-Pro WestWater % git status
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)
        modified:   gatsby-ww (modified content, untracked content)

no changes added to commit (use "git add" and/or "git commit -a")
ericphifer@Erics-MacBook-Pro WestWater % git commit -a
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)
        modified:   gatsby-ww (modified content, untracked content)

no changes added to commit (use "git add" and/or "git commit -a")
ericphifer@Erics-MacBook-Pro WestWater % git conig --list
git: 'conig' is not a git command. See 'git --help'.

The most similar command is
        config
ericphifer@Erics-MacBook-Pro WestWater % git config --list
credential.helper=osxkeychain
push.default=current
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/EricPhifer/westwaterco
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
submodule.gatsby-ww.url=https://github.com/EricPhifer/westwaterco.git
submodule.gatsby-ww.active=true
ericphifer@Erics-MacBook-Pro WestWater % git submodule deinit
fatal: Use '--all' if you really want to deinitialize all submodules
ericphifer@Erics-MacBook-Pro WestWater % git submodule deinit --all
ericphifer@Erics-MacBook-Pro WestWater % git config --list
credential.helper=osxkeychain
push.default=current
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/EricPhifer/westwaterco
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
submodule.gatsby-ww.url=https://github.com/EricPhifer/westwaterco.git
submodule.gatsby-ww.active=true
ericphifer@Erics-MacBook-Pro WestWater % rm -rf submodule.gatsby-ww.url=https://github.com/EricPhifer/westwaterco.git
ericphifer@Erics-MacBook-Pro WestWater % git config --list
credential.helper=osxkeychain
push.default=current
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/EricPhifer/westwaterco
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
submodule.gatsby-ww.url=https://github.com/EricPhifer/westwaterco.git
submodule.gatsby-ww.active=true
ericphifer@Erics-MacBook-Pro WestWater % rm -rf .git/modules/a/submodule
ericphifer@Erics-MacBook-Pro WestWater % git rm -f a/submodule
fatal: pathspec 'a/submodule' did not match any files
ericphifer@Erics-MacBook-Pro WestWater % git config --list
credential.helper=osxkeychain
push.default=current
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/EricPhifer/westwaterco
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
submodule.gatsby-ww.url=https://github.com/EricPhifer/westwaterco.git
submodule.gatsby-ww.active=true
ericphifer@Erics-MacBook-Pro WestWater % mv submodule.gatsby-ww submodule.gatsby-ww-temp
mv: rename submodule.gatsby-ww to submodule.gatsby-ww-temp: No such file or directory
ericphifer@Erics-MacBook-Pro WestWater % mv gatsby-ww gatsby-ww-temp
ericphifer@Erics-MacBook-Pro WestWater % git submodule deinit -f -- gatsby-ww
ericphifer@Erics-MacBook-Pro WestWater % rm -rf .git/modules/gatsby-ww
ericphifer@Erics-MacBook-Pro WestWater % git rm -f gatsby-ww
rm 'gatsby-ww'
ericphifer@Erics-MacBook-Pro WestWater % git config --list
credential.helper=osxkeychain
push.default=current
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/EricPhifer/westwaterco
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
submodule.gatsby-ww.url=https://github.com/EricPhifer/westwaterco.git
submodule.gatsby-ww.active=true
ericphifer@Erics-MacBook-Pro WestWater % mv gatsby-ww-temp gatsby-ww
ericphifer@Erics-MacBook-Pro WestWater % git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        deleted:    gatsby-ww

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

ericphifer@Erics-MacBook-Pro WestWater % git add .
warning: adding embedded git repository: gatsby-ww
hint: You've added another git repository inside your current repository.
hint: Clones of the outer repository will not contain the contents of
hint: the embedded repository and will not know how to obtain it.
hint: If you meant to add a submodule, use:
hint: 
hint:   git submodule add <url> gatsby-ww
hint: 
hint: If you added this path by mistake, you can remove it from the
hint: index with:
hint: 
hint:   git rm --cached gatsby-ww
hint: 
hint: See "git help submodule" for more information.
ericphifer@Erics-MacBook-Pro WestWater % git commit -m "add gatsby-ww for commits"
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)
        modified:   gatsby-ww (modified content, untracked content)

no changes added to commit (use "git add" and/or "git commit -a")
ericphifer@Erics-MacBook-Pro WestWater % 

这其中的大部分内容都在尝试遵循该线程的指示如何删除子模块?,但是您可以看到,每次我检查git config --list子模块时,它总是在那里。这是我尝试遵循的许多 stackoverflow 线程之一,但没有任何效果,所以这是我最后一次努力了解问题所在以及如何解决问题。Git对我来说太令人沮丧了,请帮助并谢谢你。

刚刚检查了另一个项目,它有同样的问题,除了它没有 gatsby 文件的子模块:

ericphifer@Erics-MacBook-Pro Joseph Center Code % git config --list
credential.helper=osxkeychain
push.default=current
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
core.ignorecase=true
core.precomposeunicode=true
remote.origin.url=https://github.com/EricPhifer/joseph-center.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.main.remote=origin
branch.main.merge=refs/heads/main
ericphifer@Erics-MacBook-Pro Joseph Center Code % git status 
On branch main
Your branch is up to date with 'origin/main'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
  (commit or discard the untracked or modified content in submodules)
        modified:   gatsby-jc (modified content)

no changes added to commit (use "git add" and/or "git commit -a")

标签: gitmacosgithubversion-control

解决方案


首先,让我们解决这个问题,因为它相对较小:

submodule.gatsby-ww.url=https://github.com/EricPhifer/westwaterco.git
submodule.gatsby-ww.active=true

这些是 Git 从.gitmodules描述子模块的文件中复制gatsby-ww到您的.git/config. Git 在克隆超级项目和子模块时会在不同的地方执行此操作,因为该.gitmodules文件包含原始 URL,但您可能希望在不影响.gitmodules文件的情况下更改此 URL。(这是.url具体的;该.active设置只是告诉 Git 的其他部分子模块正在使用中。)

因此,我们可以忽略这些:仅当/当子模块首先处于活动使用状态时才使用它们,而子模块处于活动状态的事实您的绊脚石。

一旦你修复了它——假设这个是正确的——你可以使用git config --unset submodule.gatsby-ww.activegit config --unset submodule.gatsby-ww.url删除这两个设置,或者git config --edit在文件上运行你配置的编辑器(这是INI 文件.git/config的 Git 化风格;它通常很漂亮清楚如何在任何文本编辑器中调整这些)。

刚刚检查了另一个项目,它有同样的问题,除了它没有 gatsby 文件的子模块......

这个另一个项目确实有一个子模块,虽然它被命名为gatsby-jc,而不是gatsby-ww

无论如何,让我们回到您gatsby-ww在第一个项目中取消子模块的尝试:

ericphifer@Erics-MacBook-Pro WestWater % mv gatsby-ww gatsby-ww-temp
ericphifer@Erics-MacBook-Pro WestWater % git submodule deinit -f -- gatsby-ww
ericphifer@Erics-MacBook-Pro WestWater % rm -rf .git/modules/gatsby-ww
ericphifer@Erics-MacBook-Pro WestWater % git rm -f gatsby-ww
rm 'gatsby-ww'

这些命令本身就很好。你:

  • 将现有的 Git 存储库移开gatsby-ww:这个 Git 存储库将继续存在;
  • 用于git submodule deinit清除gatsby-ww作为子模块的存在;
  • 删除了存在于的任何克隆.git/modules/gatsby-ww;和
  • 删除了索引条目,gatsby-ww使其作为gitlink存在。

我们稍后会回到最后一个细节,因为这与子模块的工作方式有很大关系。

不过这里的情况非常糟糕:

ericphifer@Erics-MacBook-Pro WestWater % mv gatsby-ww-temp gatsby-ww
ericphifer@Erics-MacBook-Pro WestWater % git add .
warning: adding embedded git repository: gatsby-ww

请注意警告:在此处添加嵌入式 git 存储库 ...消息。我已经删除了它下面的详细提示,但是这一步作为一个 submodulegatsby-ww回去了。您不能 git add现在的gatsby-ww目录,因为它包含一个.git.

关于子模块你需要知道的

子模块是 Git 让一个 Git 存储库引用另一个 Git 存储库的方式。按照设计,任何 Git 存储库都不能包含另一个 Git 存储库。这是完全禁止的——主要是出于安全目的,尽管 Git 存储在其数据库中的二进制文件自动不适合存储在另一个 Git 存储库中,所以即使它没有被禁止,这也是一个坏主意.

由于存储库实际上不能包含另一个存储库,但人们想组合或链接存储库,Git 在这里有一个“解决方案”(某种意义上):子模块。子模块在某种程度上是一种形式的声明:在你克隆了这个存储库并检查了一些特定的提交之后,你——Git——应该克隆另一个存储库。克隆其他 Git 存储库,Git 需要知道该存储库的 URL。完成克隆后,Git 需要另外一对项目:该存储库中某个提交的原始哈希 ID ,Git 应该git checkout在子存储库中,以及该签出应该作为子模块存在的路径。

Git 将“外部”存储库称为超级项目,将“内部”(子)存储库称为子模块。不幸的是,这些都以字母开头s,所以我使用RS分别表示超级项目 Repository 和 Submodule。

第一部分和第二部分的一半放入.gitmodules文件中。这列出了 URL 和路径。第二部分的一半,以及第二部分的其余部分,进入 R 中的每个提交R中的每个提交都包含一个 <pathname, hash-ID> 对。这对采用 Git 所谓的gitlink的形式。

Git 存储库中的普通文件是具有mode 100644(常规、非可执行文件)或100755(可执行文件)的实体。Git 存储库中的符号链接是一个带有mode 120000. git ls-tree -r您可以在输出中看到这些内容:

...
100755 blob 9c125f298aea6863a9370c16a0f70b7cccc73b2d    GIT-VERSION-GEN
100644 blob 66389ce05915d776e5c8ff49aea40e20bc40eb62    INSTALL
100644 blob d38b1b92bdb2893eb4505667375563f2d6d4086b    LGPL-2.1
...
100644 blob c3565fc0f8f7df81232deca663bf55e14737ae97    Makefile
100644 blob eb8115e6b04814f0c37146bbe3dbc35f3e8992e0    README.md
120000 blob f071367dc30cd9c12cc010539f4ca151d1282757    RelNotes
...
100644 blob 6102893fccb96cf2203b524664c3b2c88c84d9b1    builtin/log.c
100644 blob 45cc3b23dd6845d902e64997a80c7c7347110c6d    builtin/ls-files.c
100644 blob 1794548c71179afb68c74a231749be5f5fdae3ee    builtin/ls-remote.c
100644 blob 3a442631c71a07f0d0dda791ed72af83f2b92bca    builtin/ls-tree.c
...

git ls-tree -r以上是Git 存储库中提交的输出片段。请注意该文件GIT-VERSION-GEN是如何可执行的并且RelNotes是一个符号链接。

提交中的子模块很像任何其他文件,除了它有mode 160000. 类型 ( ) 之后的大而丑陋的哈希 ID 是commit子模块中某些提交的 ID:

160000 commit 855827c583bc30645ba427885caa40c5b81764d2  sha1collisiondetection

提交本身,以及所有的文件,都没有存储超级项目中:存储库R只包含.gitmodules文件——根据需要复制它的多个副本,每个提交减去所有通常的相同文件的重复数据删除——加上 gitlinks ,每次提交一个。这是.gitmodules文件的内容:

$ cat .gitmodules
[submodule "sha1collisiondetection"]
        path = sha1collisiondetection
        url = https://github.com/cr-marcstevens/sha1collisiondetection.git
        branch = master

(由于该文件在大多数提交中都是相同的,因此实际上只有一个共享副本。查看来自git ls-tree -r HEAD或任何其他提交的输出,以查看包含上述文本的 blob 的哈希 ID。)

这对你意味着什么

如果您希望将目录中的文件放入您在R中进行的下一次提交中,则必须删除位于. 这可以是一个目录,包含整个存储库S,也可以是一个名为 的文件,包含 Git 期望找到S的路径。无论哪种方式,它存在的事实意味着将拒绝添加文件。相反,将检测到这一个存储库,并将为S添加适当的 gitlink而不是gatsby-ww.gitgatsby-ww/.git.git .gitgit addgit addgatsby-ww 添加文件。由于这不能.gitmodules正确创建或更新,git add因此还会打印出一个很大的警告消息,说明它刚刚添加的子模块是如何半途而废的,并且可能不适用于其他任何人(包括你自己未来)。

请记住,存储库提交的集合。它不是文件的集合!某些存储库中的文件在提交中,但每个提交都有每个文件(尽管已压缩、Git 化和重复数据删除为不应存储在另一个 Git 存储库中的二进制格式)。您不能将 Git 存储库放入另一个 Git 存储库,除非通过诡计(.git例如临时重命名),并且通常您不应该这样做(因为它工作得不好)。如果使用子模块,请考虑是否使用子模块;如果你这样做了,请继续使用它们;如果没有,想想你做了什么想保留。

如果您确实想使用子模块,并且您在子模块的工作树中进行了更改,则必须:

  • 输入子模块——它是一个自己的 Git 存储库——并添加并提交更改;
  • git push其他人将从中改变的地方git clone;接着
  • 退出子模块和Sgit add的路径,以便 Git 可以使用您在提交子模块更改时所做的提交的哈希 ID 将新的、修改后的 gitlink 放入下一次提交中。

这有点不方便,但这就是子模块的工作方式。


推荐阅读