始终使用git init
在相同目录(无论我在哪里使用git init
都在同一个目录中创建具有相同名称repo的'git nude repo',将其称为'A')>
如果删除了仓库'A',然后再次执行git init
,(删除的)仓库A 将在同一目录中再次创建(如上所述)。如果我第二次执行“ git init”,则会收到以下错误,好像我的当前文件夹中包含repo A的.git。
Reinitialized existing Git repository in path/to/repo/A
创建存储库“ A”时,它将处于未出生或未绑定状态,这意味着没有分支,将在第一次提交时创建分支。
此外,git日志,git状态,有关gits状态的所有内容都属于此存储库“ A”。
我可以使用git clone,但是git status,log,commit仍然会显示,就好像它位于repo'A'git目录中一样。
git pull,push,commit属于仓库'A'git目录
由于遇到此问题,我暂时停止在本地计算机上使用git了,但是现在我需要使用它,别无选择。
我尝试重新安装git。没有帮助。
我很难调查这个问题,因为我不太了解git init在内部如何工作。
我在这里的问题如下
编辑:
我不知道为什么要放在前面。我修好了它。谢谢你指出这一点,它只是语法。问题的细节仍然是正确的。
答案 0 :(得分:3)
我想我明白这里出了什么问题。您已经在某种环境中设置了GIT_DIR
。我不知道到底是怎么做到的,但是您需要停止这样做。检查您的.bashrc
和/或.profile
文件;登录时检查在环境中可能设置GIT_DIR
的所有系统配置文件。如果使用POSIX Shell,请测试$GIT_DIR
的当前值:
$ pwd
/tmp/tmprepo1
$ echo $GIT_DIR
/tmp/tmprepo2
使用unset
命令将其取消设置:
$ unset GIT_DIR
$ echo $GIT_DIR
$ git init
Initialized empty Git repository in /tmp/tmprepo1/.git/
(这些命令是在下面的复制器上设置后运行的。)
$ cd /tmp
$ rm -rf tmprepo2 # make sure there is no /tmp/tmprepo2
$ mkdir tmprepo1 # now make /tmp/tmprepo1...
$ cd tmprepo1 # ...and enter it
$ GIT_DIR=/tmp/tmprepo2 git init
Initialized empty Git repository in /tmp/tmprepo2/
$ ls -A
$ ls -AF /tmp/tmprepo2
branches/ description hooks/ objects/
config HEAD info/ refs/
请注意,Git创建了/tmp/tmprepo2/.git
,而不是/tmp/tmprepo1/.git
。
请注意,我不仅运行git init
。我跑了GIT_DIR=/tmp/tmprepo2 git init
。我也可以运行git --git-dir=/tmp/tmprepo2 init
。 关键是我明确地告诉Git,它不应该使用我的 current 目录。在这里,我使用命令行标志进行此操作-{{1 }}或环境变量 --git=dir=/tmp/tmprepo2
,方法是在命令前设置$GIT_DIR
(使用POSIX Shell语法)。
我怀疑您没有输入GIT_DIR=...
。但是,如果我更早地 export 将该变量设置为空,则发生同样的事情:
GIT_DIR=path git init
,然后在以后的任何时间运行:
$ export GIT_DIR=/tmp/tmprepo2
您已经在环境中设置了$ git init
Reinitialized existing Git repository in /tmp/tmprepo2/
。
首先,让我们注意GIT_DIR
有两个工作:
第二项工作很少有用,但是git init
的意思是:
git init
这意味着您实际上在该(完整)路径中具有一个Git存储库。 这不是错误。这只是大多数人从未真正使用过的请求。
接下来,让我们区分Reinitialized existing Git repository in path/to/repo/A
和git init --bare
。因为有两份工作,所以这有点棘手。但是有一个相对简单的区别:
常规(非裸露)存储库是具有工作树的存储库。工作树,也称为工作树或工作树或任何数量的相似名称,是您可以查看和使用文件的地方。常规存储库由以下几部分组成:
裸存储库是没有工作树的存储库。没有工作树,则无法在此存储库中进行任何工作。您仍然可以做一些事情,但是这种存储库的真正意义是要驻留在服务器上,例如GitHub或GitLab或BitBucket之类的托管服务器,没有人 会做任何工作直接。
(出于历史和兼容性的原因,裸存储库仍具有索引。如上所述,该索引的目的主要是构建 next 提交,并帮助跟踪文件在您的工作树中,并且没有工作树,在裸存储库中的索引并不是特别有用。但是它仍然有它。)
让我们开始创建一个新的空目录git init
并进入该目录。 (我在类似于bash的POSIX shell中,在类似Unix / Linux的系统上进行所有操作。)
/tmp/tmprepo
如果我现在没有运行$ cd /tmp
$ mkdir tmprepo
$ cd tmprepo
$ pwd
/tmp/tmprepo
git init
,则Git会说:
--bare
随便看看,似乎什么都没发生,但是如果我仔细观察,告诉我的系统也显示隐藏文件(点文件),我会看到:
$ git init
Initialized empty Git repository in /tmp/tmprepo/.git/
Git已创建一个$ ls -AF
.git/
目录,正如其在输出中所示。这是一个常规的(即非裸露的)存储库。如果我再次运行.git
,但没有运行git init
,则会显示:
--bare
确实是这样做的:在不触摸$ git init
Reinitialized existing Git repository in /tmp/tmprepo/.git/
中的任何重要文件的情况下,它确保从我当前的Git安装中更新了所有 template 钩子文件。由于我没有更改Git的版本,因此没有此类更新。换句话说,这根本没有做任何事情。
如果愿意,我们可以窥视这个/tmp/tmprepo/.git/
目录,以查看常规(非裸露)存储库包含的内容:
.git
这是此常规存储库的存储库部分。请注意,存在一个名为$ ls -F .git
branches/ description hooks/ objects/
config HEAD info/ refs/
的文件,另一个名为config
的文件以及名为HEAD
,info/
,hooks/
和{{1} }。通常,您不会直接与所有这些事物进行交互,但是,由于这些文件和目录的存在,可以轻松识别内部Git目录。
目录objects/
本身是此存储库的工作树。这意味着我们可以随意创建,编辑和销毁任何我们喜欢的文件,只要我们不动手即可存放实际存储库的refs/
目录即可。
但是,如果我现在运行/tmp/tmprepo/
,则会发生这种情况:
.git
由于这里没有说已重新初始化,因此确实创建了一个新的空Git存储库。让我们看一下,使用git init --bare
或$ git init --bare
Initialized empty Git repository in /tmp/tmprepo/
选项,以确保我们真正看到了所有文件,包括现有的-a
文件:
-A
此处的.git
(目录)是较早的$ ls -AF
.git/ config HEAD info/ refs/
branches/ description hooks/ objects/
留下的。此.git
创建了一个 bare 存储库,其路径名为git init
。也就是说,它将现有的git init --bare
目录放入/tmp/tmprepo
目录中的所有相同种文件。因此,我们现在有两个存储库。
只需检查一下,我们就删除这两个存储库(两个存储库中都没有任何有价值的东西):
/tmp/tmprepo
到目前为止,这看起来是一样的。我们在.git
目录中创建了一个新的空存储库。没有$ cd /tmp
$ rm -rf tmprepo
$ mkdir tmprepo
$ cd tmprepo
$ git init --bare
Initialized empty Git repository in /tmp/tmprepo/
$ ls -A
branches description hooks objects
config HEAD info refs
,因为上次是非裸存储库的/tmp/tmprepo
目录。现在:
.git
这没有说已重新初始化,因此它再次创建了一个新的非裸存储库。
很可能在同一个目录中同时包含一个 和 non-bare 存储库。这不是一个好情况,因为在这种情况下,应该使用哪个存储库不再是显而易见的。
我们可以使用tmp/tmprepo/.git/
测试Git的实际功能。 rev-parse命令现在有 lot 个选项,包括$ git init
Initialized empty Git repository in /tmp/tmprepo/.git/
。在这个git rev-parse
(本身是git rev-parse --is-inside-work-tree
中的裸仓库和/tmp/tmprepo
中的非裸仓库以及/tmp/tmprepo
中的工作树)中,我们发现:
/tmp/tmprepo/.git
如果我们删除此设置的非裸仓库部分,然后重试,则会发现:
/tmp/tmprepo
我们现在只能使用 bare 仓库,因此我们不在工作树中,因为裸仓库没有工作树。
同时删除两者:
$ git rev-parse --is-inside-work-tree
true
让我们重新开始。
创建存储库“ A”时,它将处于未出生或未绑定状态,这意味着没有分支,将在第一次提交时创建分支。
存储库本身将没有任何提交。一个新的空存储库没有提交。
任何Git存储库中的分支名称均指一(1)个现有提交。由于新的空存储库没有提交,因此分支名称将不存在。
尽管如此,Git仍然声称您在某个分支上。这就是所谓的未出生分支。
git init如何在内部工作?在哪种情况下会发生我的问题?
目前为止您还不清楚,您的实际问题是什么。
如何解决此问题?通过修复我的意思,我只想使用git init,即使用它的方式。
您可能想运行一次$ rm -rf .git
$ git rev-parse --is-inside-work-tree
false
,没有 $ cd ..
$ rm -rf tmprepo
,在已经是某些树的顶层目录中创建git init
目录准备成为或将成为您的工作树。如果此目录中有一些现有文件,则可以。
运行--bare
后,您现在将拥有一个.git
目录。 git init
命令应该可以工作,并且应该告诉您尚无提交。
您现在可以.git
希望在第一次提交中的每个文件。进行一次仅包含git status
文件和/或其他描述性元素(例如git add
文件)的第一次提交是一个不错的主意,但是您README
保留了哪些文件给你。使用LICENSE
将每个添加的文件复制到Git的索引中(我们在上面已经提到过);索引中的文件将是第一次提交的文件。然后运行git add
对当前索引中的内容进行快照。此新快照将是存储库中的第一个(并且现在是)提交。
第一次提交后,初始分支名称(通常为git add
)将存在。索引将继续包含已提交文件的副本(实际上是对已提交文件的引用)。添加更多文件,和/或更改工作树文件和git commit
任何现有文件,以覆盖更新版本的索引副本,然后再次master
创建新快照。新的快照-存储库中的 second 提交-将包含索引中所有文件的冻结副本,以及指向第一个提交的链接。 Git将更新您当前的分支名称git add
,以记住新提交的原始哈希ID。