Ale*_*ani 15 git branch github
我需要在创建分支时确认/更正我的假设.如果我在主分公司,做完之后:
git checkout -b some_branch
Run Code Online (Sandbox Code Playgroud)
这意味着我已经从master开始了一个新的分支.
另一方面,如果我签出另一个分支,并在那里创建一个分支:
git checkout some_branch
git checkout -b other_branch
Run Code Online (Sandbox Code Playgroud)
这意味着我使用some_branch提交的所有当前代码创建了other_branch,对吧?
并且,无论当前分支如何,如果这样做:
git branch branch_2 branch_1
Run Code Online (Sandbox Code Playgroud)
然后使用branch_1作为基础创建branch_2.这些假设是否正确?
tor*_*rek 21
在Git中没有这样的东西作为分支的基本分支.相反,只有一个当前提交,Git称之为分支的提示.
要理解这一点,你应该从绘制(至少部分)Git的提交图开始.这是一个只有三个提交的小型存储库的示例:
A <-B <-C <--master
Run Code Online (Sandbox Code Playgroud)
任何给定提交的"真实名称"是那些丑陋的哈希ID之一,c0ffeeface1deadbead...
依此类推.该散列ID唯一地识别特定的提交,并且实际上是由通过散列(因此命名为"散列ID")的内容的该提交.它们看起来是随机的,不可能记住,所以在这里我只使用单个大写字母.
Git"看到"图形的方式是它通过读取分支名称开始,例如master
.此分支名称包含提交的哈希IDC
.我们说master
要提交点C
.
同时,commit C
本身包含其先前(或父)提交的哈希ID B
.所以我们说C
点B
,以同样的方式master
指向C
.
同样,提交B
点返回A
. A
是有史以来第一次提交,所以没有任何地方可以指向......所以它不会.我们称A
一个根承诺,它让我们(和Git)停止向后工作.
这些内部箭头有点令人讨厌,并注意到哈希ID B
实际上是 C
其自身的一部分,所以它永远不会改变(如果我们试图改变这一部分C
,我们会得到一个新的,不同的提交).所以我们可以停止打扰它们,然后写:
A--B--C <-- master
Run Code Online (Sandbox Code Playgroud)
出来一个的箭头分行的名称,不过,是不是恒定的,而这也正是在这种整体思路提示提交从何而来.
假设我们要添加一个新的提交master
.我们执行Git所需的所有常规设置(添加或修改某些文件并使用git add
),然后运行git commit
.Git的方法:
写出一个新的提交D
(获取一个新的,唯一的哈希ID).这个新提交指回C
:
A--B--C <-- master
\
D
Run Code Online (Sandbox Code Playgroud)然后,更改 master
(或更准确地说,它存储的哈希ID),以便它指向我们刚刚进行的新提交:
A--B--C
\
D <-- master
Run Code Online (Sandbox Code Playgroud)
当然,没有理由再在图纸中保持这种扭结:
A--B--C--D <-- master
Run Code Online (Sandbox Code Playgroud)所以这就是Git中分支增长的方式.
要创建一个新分支,Git只需创建指向某个现有提交的分支名称:
A
\
B
\
C
\
D <-- master
Run Code Online (Sandbox Code Playgroud)
我们可以选择其中任何一个提交,并在那里创建一个新的分支名称.让我们来挑选B
并newbr
指出:
A
\
B <-- newbr
\
C
\
D <-- master
Run Code Online (Sandbox Code Playgroud)
我们会这样做git branch newbr <thing-that-finds-B>
.
我们怎么找到B
?好吧,一种方法是运行git log
并剪切并粘贴哈希ID.但另一种方法是使用分支名称.这个名字newbr
现在指向B
.如果我们想要另一个分支点也提交B
:
git branch thirdbr newbr
Run Code Online (Sandbox Code Playgroud)
这使Git查找newbr
,指向B
并创建新名称thirdbr
,其中......也指向B
:
A--B <-- newbr, thirdbr
\
C--D <-- master
Run Code Online (Sandbox Code Playgroud)
这就是为什么在Git中创建一个分支的速度非常快:它几乎什么都没做!它只是制作一个指向某个现有提交的标签.
一些分支名称点的提交称为该分支的提示提交.请注意,一次提交可以同时是几个分支的提示.这是关于Git的一个更大的事情的一部分:一些提交在许多分支上,所有这些都在同一时间.例如,提交A
- 根提交 - 在每个分支上.(它可能在存储库中有多个root提交,虽然它有点棘手,我们现在不需要担心.你不能用到目前为止显示的命令来做到这一点.)
然而,分支标签的特殊属性是它们会移动.它们不仅会移动,而且会自动移动.
我们在做出新提交时已经看到了这一点D
.Git将新提交的ID写入master
.但是:Git是如何使用的master
? 就此而言,Git是如何让D
父母知道的C
?
嗯,当然,我们只是在当时一个分支,但让我们做一个新的承诺,现在,现在我们有三个标签master
,newbr
和thirdbr
.首先,让我们做git checkout thirdbr
,并绘制结果:
A--B <-- newbr, thirdbr (HEAD)
\
C--D <-- master
Run Code Online (Sandbox Code Playgroud)
在图中,在没有真正改变1不同的是我加的话HEAD
在这里.HEAD是Git知道哪个分支和提交是当前分支和提交的方式.
所以现在我们做我们通常的修改 - 文件git add
,和git commit
.Git写出了新的提交,其父设置为commit B
.Git看到当前分支是thirdbr
并thirdbr
指向B
,所以当前提交是B
.让我们在新提交中绘制E
:
E
/
A--B <-- newbr
\
C--D <-- master
Run Code Online (Sandbox Code Playgroud)
剩下的唯一事情就是移动当前的分支名称 thirdbr
,使其指向新的提交E
:
E <-- thirdbr (HEAD)
/
A--B <-- newbr
\
C--D <-- master
Run Code Online (Sandbox Code Playgroud)
我们都完成了:我们已经为分支添加了一个新的提交thirdbr
(它仍然是HEAD,因此仍然是当前分支,但现在E
是当前的提交).
当您向当前分支添加提交时,它是HEAD,它告诉当前提交是什么以及新提交的位置. HEAD通常包含分支的名称,这就是git checkout
:它检查特定的提交 - 通常是现有分支的提示 - 然后设置文件HEAD
以记住分支的名称.这是分支名称本身,它记住了提示提交.
使用方法:"检查指定的提交,然后创建一个指向该提交的新分支名称newname,然后将HEAD设置为该新名称." 如果省略提交部分,则默认使用HEAD.由于HEAD 是(总是)当前提交,Git会得到跳过"退房"的一部分,只是创建新的分支名,并将其存储到文件中.git checkout -b newname commit
HEAD
1虽然没有在改变图形,Git的根本需要更新我们的工作树和索引,这样我们就可以有文件作为他们在提交的方式B
.