如何确保对主分支的git提交不是偶然的?

时间:2018-01-27 20:57:39

标签: git version-control repository

我初始化了一个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分支?

2 个答案:

答案 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 statusgit 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

分支名称包含哈希ID

至少在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写入分支名称。

这意味着对于存在的分支名称,它必须包含哈希ID

此时您尝试dev,但没有名为master 的分支。所以你改为:

git checkout master

告诉Git继续并创建名称git checkout -b master ,指向当前提交。

当前提交是存储库中的(单个)提交,名称master已指向该提交。所以现在你有两个分支名称devdev指向那个提交:

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)

首先,解释为什么会遇到这种情况。

  1. 为什么第一次使用git checkout master时主分支没有被重新识别

    初始化git repo时,默认分支名称为mastermaster分支上没有任何版本(提交)。您没有在master分支上提交更改,而是切换到dev分支(git checkout -b dev)并在dev分支上提交了更改。这意味着丢弃master分支并改为使用dev分支并在dev分支上提交更改。如果您使用git branch,则仅在此时列出dev分支。

  2. 为什么masterdev分支

    显示相同

    当您在git checkout -b master分支上执行命令dev时,git将从master(在HEAD分支上)创建新分支dev ,然后将HEAD切换到新创建的分支master。因此master也会指向您在dev分支上提交的提交。

  3. 在大多数情况下,分支通常具有相同的祖先。如果您不希望master分支与dev分支具有相同的祖先,则可以将master分支更改为孤立分支(与{{1}无关的历史记录分支):

    dev