在Git中删除分支时会发生什么

在Git中删除分支时会发生什么,git,branch,git-branch,Git,Branch,Git Branch,我寻找这个问题的答案已经有一段时间了,但仍然不能完全确定它的答案。 我发现的关于删除分支的大多数信息只不过是手册所述内容的副本(例如)。 我认为一个核心问题是我不知道Git中的分支是什么(尽管有很多文章声称对此进行了解释)。 我找到的唯一有用的信息是和git一起安装的文档 我的问题: 当我运行git branch-d branch\u NAME时 引擎盖下发生了什么 外部发生了哪些变化,即我与存储库的交互如何变化 这些变化中有哪一个可以被认为是历史上的变化 另外,git branch-D bra

我寻找这个问题的答案已经有一段时间了,但仍然不能完全确定它的答案。 我发现的关于删除分支的大多数信息只不过是手册所述内容的副本(例如)。 我认为一个核心问题是我不知道Git中的分支是什么(尽管有很多文章声称对此进行了解释)。 我找到的唯一有用的信息是和git一起安装的文档

我的问题:

当我运行
git branch-d branch\u NAME

  • 引擎盖下发生了什么
  • 外部发生了哪些变化,即我与存储库的交互如何变化
  • 这些变化中有哪一个可以被认为是历史上的变化
  • 另外,git branch-D branch\u NAME的子问题也相同

    我目前的理解:

    首先,我对一个分支的看法: 根据上下文的不同,术语branch指的是指向某个提交的指针(严格称为分支头),或者是指向该提交的提交列表

    对于
    git branch-d branch\u NAME
    ,我认为会发生什么(但我很不确定):

  • 指向分支头的指针将被删除,不再显示
  • 我再也看不到任何列表中的分支了,我再也不能切换到它或从它开始分支(尽管我想我可以在提交时创建一个新分支,以有效地实现这些事情)
  • 可能不会:提交仍然存在,只是不再标记分支的名称
  • 我认为发生了什么,对于
    git branch-D branch\u NAME

  • 将删除指向分支头的指针,并删除不在其他分支上的任何提交
  • 我再也看不到任何列表中的分支了,我再也无法切换到它或从中分支,也无法以任何方式检索代码
  • 是:分支中的提交已丢失

  • 在分支移除之后,提交仍然存在,直到下一次垃圾回收
    git branch-d
    (和
    -d
    )打印缩写的提交散列,您可以将其用作
    git log
    git checkout
    git branch
    的参数,这样您就可以恢复已删除的分支


    -d
    -d
    之间的唯一区别在于
    git branch-d
    不允许删除未合并的分支(即可能丢失提交)。

    无论您是使用
    git branch-d
    还是
    git branch-d
    删除,git都不会删除提交,而只删除分支引用。继续读下去,看看这意味着什么

    首先,我们将建立一个简单的演示历史记录

    $ touch initial ; git add initial ; git commit -m 'Initial commit'
    [master (root-commit) 2182bb2] Initial commit
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 initial
    
    $ git checkout -b mybranch
    Switched to a new branch 'mybranch'
    
    此时,
    master
    mybranch
    都指向同一个分支 提交,我们至少可以通过两种方式进行验证

    $ git lola
    * 2182bb2 (HEAD -> mybranch, master) Initial commit
    
    请注意,
    git lola
    是一个非标准但非常有用的别名, 相当于

    $ git log --graph --decorate --pretty=oneline --abbrev-commit --all
    * 2182bb2 (HEAD -> mybranch, master) Initial commit
    
    另一种方法是在
    mybranch
    上创建一个新的提交后再看

    $ touch mybranch ; git add mybranch ; git commit -m 'My branch'
    [mybranch 7143aa4] My branch
     1 file changed, 0 insertions(+), 0 deletions(-)
     create mode 100644 mybranch
    
    这样做之后,我们确实在多个分支上有多个提交

    $ git lola
    * 7143aa4 (HEAD -> mybranch) My branch
    * 2182bb2 (master) Initial commit
    
    我们现在可以看看git是如何在幕后实现这一点的

    $ ls -R .git/refs
    .git/refs:
    heads  tags
    
    .git/refs/heads:
    master  mybranch
    
    .git/refs/tags:
    
    奇怪的是,有些文件与我们的分支机构同名。 从里面看,我们看到

    $ cat .git/refs/heads/master .git/refs/heads/mybranch
    2182bb2d5a0a7f57d0b74e95d37e208dac41f95b
    2182bb2d5a0a7f57d0b74e95d37e208dac41f95b
    
    所以git将refs实现为特定位置中名称匹配的文件 包含SHA1的分支名称和 某些提交的散列。请注意,
    git lola
    2182bb2
    )输出中的缩写哈希是上述
    cat
    输出的前导前缀

    将git引用视为简单的指针,为存储库历史中的特定提交提供人类可读的名称

    现在,如果我们切换回
    master
    和zap
    mybranch

    $ git checkout master ; git branch -D mybranch
    Switched to branch 'master'
    Deleted branch mybranch (was 7143aa4).
    
    我们看到裁判走了

    $ ls -R .git/refs
    .git/refs:
    heads  tags
    
    .git/refs/heads:
    master
    
    .git/refs/tags:
    
    但承诺仍然存在

    $ git show --pretty=oneline 7143aa4
    7143aa477735382e7a0ed11c9e4b66c1f27583df My branch
    diff --git a/mybranch b/mybranch
    new file mode 100644
    index 0000000..e69de29
    
    如果您想
    mybranch
    返回,只需运行

    $ git checkout -b mybranch 7143aa4
    Switched to a new branch 'mybranch'
    

    取决于,正如其各自输出的差异所示, 是否要切换到分支。在后一种情况下, 在您目前所在的分支上,
    git lola
    看起来像

    $ git lola
    * 7143aa4 (mybranch) My branch
    * 2182bb2 (HEAD -> master) Initial commit
    
    是的,即使删除了使其保持活动状态的指针,您的提交也会在短时间内挂起。这在意外删除的情况下非常有用。另见和


    请注意,存储库中的SHA1哈希将不同 因为你的名字和电子邮件地址至少会有所不同 从我用过的

    为完整起见,
    -d
    -d
    之间的区别在于小写版本稍微安全一些

    -d

    ——删除

    删除分支。分支必须完全合并到其上游分支中,或者如果没有使用
    --track
    --set upstream
    设置上游,则必须完全合并到
    HEAD

    -D

    --delete--force
    的快捷方式

    -f

    ——强制

    如果branchname已经存在,请将branchname重置为startpoint。没有
    -f
    git分支拒绝更改现有分支。与
    -d
    (或
    --delete
    )结合使用,允许删除分支,而不管其合并状态如何


    我没有比花一个小时浏览所有文件夹并打开.git目录中的所有文件来轻松了解其工作原理更好的建议了。这真的很简单,做得很好。要浏览“objects”子目录,请使用
    git cat file-p
    ,后跟sha1。在日常使用中,理解git是如何工作的真的很有帮助……应该注意的是,git不会永远保持提交。只有当存在某些引用方式(直接或间接)时,提交才会无限期地存在。
    $ git lola
    * 7143aa4 (mybranch) My branch
    * 2182bb2 (HEAD -> master) Initial commit