无法将文件夹添加到git repo

时间:2019-02-27 13:59:05

标签: git git-add

我认为这个问题已经在此问题下讨论过:

Recursively add the entire folder to a repository

但是我仍然无法将某些文件夹添加到git存储库中,我需要帮助。

$ git status
...
# modified:   folder_to_add1 (modified content, untracked content)
# modified:   folder_to_add2 (modified content, untracked content)

这些文件夹最初属于另一个git存储库,因此我进入了这些文件夹并删除了其中的.git文件夹。

然后我跑了

$ git add folder_to_add1
$ git add folder_to_add2
$ git status 
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#   (commit or discard the untracked or modified content in submodules)
#
# Untracked files:
#   (use "git add <file>..." to include in what will be committed)
#
#       ../filestore/
#       ../../stdout
no changes added to commit (use "git add" and/or "git commit -a")

folder_to_add1和folder_to_add2都不能提交。

我的仓库中没有.gitignore文件。

我还能尝试什么?谢谢。


我将尝试添加有关我的原始帖子的更多信息,该帖子在上一行之前结束。感谢您对“此”被认为是进一步澄清我的原始问题的正确战争的评论,我是一个完整的新手。

亲爱的torek,非常感谢您的详细回答。我想我必须非常仔细地阅读它才能理解与子模块概念有关的细微差别。我猜子模块非常类似于我更熟悉的“ svn externals”。

从您的答案的十分钟阅读中,我的答案是:“我根本不需要子模块或subgit”。我的意思是:我希望这些最初是子模块的文件夹成为一个项目的一部分,而不是许多项目的一部分(使用数字)。

我确定您的答案在某处告诉我为什么会发生这种情况,但事实是我需要将我的项目从一台PC复制到另一台PC,并使用git来执行,这些文件夹实际上不包含在不管是否存在.git子文件夹,都使用“ git add”进行索引。

“。gitmodules”文件似乎不存在。运行后:

$ find . -name .gitmodules -print 

在项目的主文件夹中,没有任何结果。

我能够将这些文件夹添加到新的(不同的)存储库中的操作是:

$ cp -r myproject /home/myusername/newproject
$ cd /home/myusername/newproject/folder_to_add1
$ rm -r .git
$ cd ../folder_to_add2
$ rm -r .git
$ cd /home/myusername/newproject
$ git init
$ git add .
$ git commit -m "Adding all existing files to the new repository"

但是我认为我是通过这种方式来放弃所有文件更改历史记录的。

2 个答案:

答案 0 :(得分:2)

只要您看到:

modified: some-name (modified content)

git status输出中,这意味着您的 Git存储库认为名为some-name的目录是某些 other Git存储库的一部分。 (请注意,此处的子目录/文件夹名称some-name中不会以斜杠结尾。)

我认为对这个问题有所帮助的一种方法是假装涉及多个Git(因为有):一种是在您的存储库中工作的您的 Git,另一种是在您的存储库中工作。这种情况是在第二个Git存储库中工作的文件夹或子目录的Git。在某个时候,它(至少是曾经是)是第二个Git存储库。

这需要重复:这个子目录/文件夹确实以前的其他一些Git存储库。它可能还是不是第二个存储库。此外,您自己的Git存储库已经以某种方式记录了另一个Git的存在。如果您的Git存储库没有记录该记录,您将看到:

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

        subgit/

不过,您看到的是:

Changes not staged for commit:
...
        modified:   subgit (modified content)

因此,您的 Git存储库的git status输出显示modified contentuntracked content的事实意味着您的存储库为十分确定,该子目录是 other 存储库。您的存储库正在报告 other 存储库的相对状态。

如果您使用git status -uallgit status --untracked-files=all(它们表示相同的意思,-u--untracked-files=的缩写),您可以得到另一个提示:如果您的Git 认为该子目录包含另一个Git存储库,它将在子目录内部查找并告诉您该目录中的每个文件。如果您的Git确信该子目录是其自己的Git存储库,则它不会在其中查看并报告每个文件-但您的Git也不会说“修改后的内容”或这样的“未跟踪内容”。

要怎么做取决于最终要发生的事情

首先,我们需要讨论子模块。

子模块

Git有一个称为 submodules 的概念。有人称它们为“ sob-modules ”,因为它们使程序员感到哭泣。子模块实质上意味着:我告诉我的Git记录有关另一个Git存储库的信息。

现在,请考虑克隆Git存储库的方式。它使用一个简单的命令:git clone url name,甚至可能只是git clone url,结果克隆将根据URL进入目录/文件夹名称。 (提供 name 参数将选择目录/文件夹名称,而不是由URL指示。)

因此,如果您的存储库(由于它负责监督某些子Git,我们将其称为 superproject )将引用某些 other 存储库,那么您的Git是什么需要的是:

  • 它应该克隆的URL
  • 克隆时应使用的目录/文件夹名称

这两个信息存储在 proper 子模块中,存储在超级项目顶层的名为.gitmodules的文件中。

创建超级项目的 new 克隆需要此.gitmodules文件。仅在 new 克隆中才需要!如果您已经有一个克隆,并且可以正常工作并且正在管理其子存储库,则.gitmodules文件的内容不再重要。

无论是否使用.gitmodules,您的Git还会记录更多关于子模块的关于

每个Git存储库都包含三个部分:

  1. Git本身存储.git存储库。其中包含几个您不需要自己摸索的数据库。
  2. Git还存储称为 index 临时区域缓存的各种内容。调用的名称取决于Git的调用者是谁或哪个部分,但是这三个名称都是同一事物的名称。
  3. Git为您提供了一个工作树。 Git存储库中的文件以特殊的,冻结的,压缩的,仅Git的格式存储。不能更改。可以添加到,就像添加更多版本的文件一样,但是它们都只是历史记录。因此,您需要一个可以使用普通非Git格式在 at 文件中进行操作的地方。那就是你的工作树

工作树通常是您最常使用的Git的一部分-自然,它就在名称中,不是吗?但是,从某种意义上说,Git并没有真正使用工作树。它将文件放入其中,供您使用;并且当您运行git add时,您的Git将工作树的文件 out 复制到上面#2中的文件中:它们进入 index 。 / p>

当Git进行 new 提交时,Git使用 index 中的文件。首先是在文件中 的索引中存在 。当Git填充工作树时,使用git checkout提取提交,Git首先填充您的 index 。所有真正的Git动作都在该索引中进行:现有的提交进入其中,并从中进行新的提交。因此,真正重要的是索引,而不是工作树,至少就新提交而言。不管您在工作树中做什么,Git都会真正关注索引。 这就是为什么您必须一直使用git add的原因:它是每个文件的副本,在 索引中对Git至关重要。

简而言之,您的索引包含将在您进行的下次提交中使用的内容。它内部具有文件的所有全部副本,该副本为预先Git格式,可永久冻结的格式。这就是使您的索引如此重要的原因。如果您更改工作树文件,则必须使用git add复制(和Git-ify)该文件以准备下一次提交。

因此,对于Git来说,重要的是 commits ,它们由其丑陋的哈希ID标识,它们是唯一的:没有两个不同的commit都具有相同的hash ID,并且 index < / em>用于进行 new 提交。您使用工作树进行工作,但是随后您更新了Git的索引,并让Git从中进行新的提交。

这也是子模块再次出现的地方。如果您的Git充当超级项目,例如监督名为subgit/的某个文件夹中的某个子Git,则您的 Git将记录 Git的提交哈希ID ,在您的索引中!

想一会儿。您的Git不会保存其Git的文件。您的Git知道,如果他们的Git(位于您的subgit/文件夹中的Git)已在一次提交中保存了一些文件,那么提交哈希ID永远是很好的。一个简单的哈希ID(可能很大又很丑陋)以永久保存的形式唯一地标识了所有这些文件。因此,您的Git不需要 保存文件。它要做的就是保存他们提交的哈希ID。

这正是您的超级项目Git所做的。您的Git并没有保存文件(它们的文件),而是在索引中保存了它们的 commit hash ID 。然后,由于它在您的索引中,所以它也进入了您的提交。 从现在开始,您所做的每个新提交都包含其哈希ID。如果您想记录一个不同哈希ID,请告诉他们-另一个Git,一个是控制subgit/文件夹-切换到其他提交哈希ID,或进行全新的提交;然后 your Git在索引中记录了该哈希ID,以便您的 next 提交具有正确的子项目哈希ID。

请注意,即使没有.gitmodules文件,所有这些操作也可以正常工作。但是,如果您没有.gitmodules文件,则该超级项目将监督其他一些Git存储库在这里,但以后将无法轻松克隆它。

现在,您必须决定:是否要子模块?

如果您想要 子模块,那么您已经在这里-或至少在其中一半。如果您有一个.gitmodules文件列出了子项目存储库,那么您的超级项目已经为以后的克隆记录了正确的URL和名称。如果没有,您可能应该使用.gitmodules创建一个git submodule add文件。另请参见How to `git submodule add` Existing sub Repository?(这回答了如何修复最初未正确添加但您想要用作适当子模块的子项目存储库的问题。)

因此,您需要一个子模块,并且已经在.gitmodules中拥有它

鉴于您已确定要要使用一个子模块,并且已正确记录了所有子模块,因此现在要做的是 not {{1} }。正如您已经看到的那样,它什么也没做!

相反,您需要做的是开始一个新会话,方法是git add subgit-进入子模块,或者打开一个新窗口以开始在子模块中工作,或者执行任何操作。现在您在一个新的不同的存储库中!但是,哦,您可能处于分离式HEAD 模式。

没关系:您可以选择在此模式下工作。或者,您可以运行cd进入某个分支,或者运行git checkout somebranch在当前提交时创建一个 new 分支。您应该对 this Git存储库进行有意义的操作。

现在您位于这个新的不同存储库中,您可以照常使用工作树进行工作。将所有文件按所需方式排列后,在所需分支上,您将git checkout -b newbranch个修改过的文件和/或git add个未跟踪的文件复制到索引中。然后,您git add结果。现在您有了一个新的提交,您可以git commit,也可以使用 this 存储库中的这些提交进行任何操作。

现在您已经完成了在子项目中保存更新和/或新文件的新提交,现在,您可以返回到超级项目。您git push返回到超级对象,或者关闭此窗口,或者其他,然后在超级项目中继续工作。

现在,您在超级项目中要做的所有事情都是运行cd。如果子项目名为git add subproject,则仅subgit。这会将子存储库的 commit hash ID 复制到您的 index 中,因此现在可以进行提交了。添加您喜欢的其他任何内容,然后运行git add subgit进行新的提交,该提交将永久冻结所有索引内容。这样可以保存您的文件以及子项目的 commit哈希ID ,所有这些文件都准备好进入索引了。

所以您根本不需要子模块或subgit

这有点困难,尤其是在非常老的Git版本中。 Modern Git使它变得更加容易。因此,在这里,我将整个答案外包给How do I remove a submodule?,请注意,大多数答案(包括this short one for modern Git)都认为您还将删除整个工作树子存储库。如果您想保留工作树,最简单的方法就是将其移动或复制到其他地方。 请确保保存已修改和/或未跟踪的文件,因为它们可能不在子存储库中的任何提交中。

答案 1 :(得分:0)

上面的长答案很好,但是解决该问题的TL; DR是:

  1. 删除子仓库的.git仓库
  2. 运行git rm -r --cached .
  3. 运行git add .

然后git status应该会向您显示添加的文件夹