我初始化了一个git repo并希望只将所有内容放在dev分支中,而不是也放在master分支中,所以我使用了这个命令序列:
$git checkout -b dev
$git add .
$git commit -m [I added a string message]
此时git log显示HEAD处于开发状态。
然后我试着用这个回到主分支:
$git checkout master
但我得到的错误是"掌握"没有得到承认,所以我这样做了:
$git checkout -b master
现在日志显示头部既是开发人员又是主人。
当我这样做时:$git ls-tree -r --name-only master
我将所有文件显示为与使用dev时的文件相同。
我是如何搞砸的,如何确保我的文件没有提交给主分支,只提交给dev分支?
答案 0 :(得分:1)
这一切都很正常。真的没什么可做的(好吧,除了"习惯于Git&#34中的这类事情)。
我初始化了一个git repo ......
让我们在这里说得很清楚。我假设你做了这个,或者说是足够等同的东西:
$ mkdir newrepo
$ cd newrepo
$ git init
Initialized empty Git repository in ...
如果是这种情况,那么您处于一个有趣的情况:
$ git status
On branch master
No commits yet
nothing to commit (create/copy files and use "git add" to track)
$ git branch
$
也就是说,当您on branch master
表示git status
时,分支master
实际上不存在!您'在一个不分支的分支上!
所以我使用了这个命令序列:
$ git checkout -b dev $ git add . $ git commit -m "some message..."
这一切都很好,但让我们来看看git checkout -b
之后会发生什么:
$ git checkout -b dev
Switched to a new branch 'dev'
$ git status
On branch dev
No commits yet
nothing to commit (create/copy files and use "git add" to track)
$ git branch
$
换句话说,唯一改变的是,我们已经从不存在的分支master
变为分支dev
那不存在。
现在我们将一些文件添加到存储库并提交,我们看到这个输出(由于各种原因,我的产品会有所不同):
$ echo example > README
$ git add README
$ git commit -m initial
[dev (root-commit) 8ab55c8] initial
1 file changed, 1 insertion(+)
create mode 100644 README
$
此时git status
和git branch
的输出会发生变化:
$ git status
On branch dev
nothing to commit, working tree clean
$ git branch
* dev
$
由于这个Git相当现代,git status
已从(新的)No commits yet
输出切换为新的和空的repo到Git使用的更典型的nothing to commit, working tree clean
消息因为Git 1.6如果不是更早(尽管随着时间的推移会有轻微的措辞变化)。我们在分支dev
上,分支dev
存在。如果我们使用所谓的plumbing命令,我们可以看到名称dev
标识的哈希ID:
$ git rev-parse dev
8ab55c84b79cad21440187b4f95ce7c3b947064b
这是我们在git commit
输出中看到的长版本,当它说:
[dev (root-commit) 8ab55c8]
告诉我们刚刚创建了一个新提交,即新提交是一个 root 提交(没有父提交),这个新提交的缩写哈希ID是{{1}并且新提交导致更新 - 或者在这种情况下,创建 - 分支名称8ab55c8
。
至少在Git中的分支名称只是一个人类可读的哈希ID名称,还有另一个特殊属性。它是定位提交的哈希ID而不是名称: name 用于查找哈希ID。在一个相当真实的意义上,哈希ID 是提交;只有一些数据与相关联的哈希ID,我们可以在这里看到:
dev
这些数据给了我们 - 或者更确切地说是Git-Git需要找到与提交一起的文件(通过一个稍长且过时的过程):
$ git cat-file -p 8ab55c8 | sed 's/@/ /'
tree 5c7082135e61da9ffc72ae2cd7d29fe702315004
author Chris Torek <chris.torek gmail.com> 1517087854 -0800
committer Chris Torek <chris.torek gmail.com> 1517087854 -0800
initial
但这里的关键是一切都按哈希ID工作;名称$ git cat-file -p 5c70821
100644 blob 33a9488b167e4391ad6297a1e43e56f7ec8a294e README
$ git cat-file -p 33a9488
example
仅用于定位第一个 - 或者我们应该说 last -hash ID。 (Git喜欢向后工作:一切都是最后的或最新的,从那里我们发现以前需要的东西。这不仅更方便我们使用 Git,它&#39;也是必需的,因为一旦存储,所有内容都是完全只读的。)
添加 new 提交包括写出提交(需要首先收集其数据并写出其树),然后使当前分支名称指向新提交。新提交一旦创建,就包含 分支提示的提交的哈希ID。 (新提交的哈希ID是在现场创建的,来自所有进入新提交的数据。)这是分支名称的另一个特殊功能:当你&#39; &#34; on&#34;一个特定的分支,添加一个新的提交告诉Git将新提交的哈希ID写入分支名称。
此时您尝试dev
,但没有名为master 的分支。所以你改为:
git checkout master
告诉Git继续并创建名称git checkout -b master
,指向当前提交。
当前提交是存储库中的(单个)提交,名称master
已指向该提交。所以现在你有两个分支名称dev
和dev
,都指向那个提交:
master
o <-- dev, master (HEAD)
部分切换Git的想法&#34;哪个分支是当前分支&#34;是git checkout
。 提交已经存在; 分支名称是新的(由master
创建);现在,-b
已附加到新分支名称。
如果你现在进行新的提交,Git将构造新的提交,它将获得一个新的哈希ID,以便新提交记住 - &#34;指向&#34; - 当前提交。然后,它会将新提交的哈希ID写入HEAD
:
master
现在o <-- dev
\
o <-- master (HEAD)
上有两次提交,master
上有一次提交。
要合并分支(稍后),两个分支应该有一些共同的提交。 Modern Git不会在没有dev
的情况下合并不相关的分支。合并不相关的历史也可能有点棘手;它不是你第一次合并时想要做的事情。旧版本的Git会在没有警告的情况下合并不相关的历史记录(对于创建仍然有点棘手)。因此,虽然它可能,但这不是你应该做的事情。
答案 1 :(得分:0)
首先,解释为什么会遇到这种情况。
为什么第一次使用git checkout master
时主分支没有被重新识别
初始化git repo时,默认分支名称为master
,master
分支上没有任何版本(提交)。您没有在master
分支上提交更改,而是切换到dev
分支(git checkout -b dev
)并在dev
分支上提交了更改。这意味着丢弃master
分支并改为使用dev
分支并在dev
分支上提交更改。如果您使用git branch
,则仅在此时列出dev
分支。
为什么master
与dev
分支
当您在git checkout -b master
分支上执行命令dev
时,git将从master
(在HEAD
分支上)创建新分支dev
,然后将HEAD
切换到新创建的分支master
。因此master
也会指向您在dev
分支上提交的提交。
在大多数情况下,分支通常具有相同的祖先。如果您不希望master
分支与dev
分支具有相同的祖先,则可以将master
分支更改为孤立分支(与{{1}无关的历史记录分支):
dev