这里不多bb,直接上结论
一、
结论
在顺序创建分支时(即:一个接一个创建,不在同一个节点创建多个分支),你所有的分支都是这样的:
在一条直线上,只是有的为了方便理解才将合并分支的过程画成多分叉的图,看自己具体在哪个分支上,完全取决于head的指向,合并也只不过是head指针的移动!
如果像图中这样创建的分支,如果dev没有提交,那么你在bug分支删除dev分支是完全可以的,而且只需要使用branch -d的方法,因为此时,你的dev分支就是你bug分支的一部分!
不能在bug分支上直接合并dev,是因为bug就是版本中最新的(即:在整个git链上是最前面的一个)。
实验
首先创建一个dev分支,并修改保存,查看分支:
$ git log --graph
* commit 70124a11f30e6cdcaca90bb2ba173ccf8f8bf20c (HEAD -> dev)
| Author: *
| Date: Mon Jul 13 14:50:53 2020 +0800
|
| dev have a branch
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
从这里也可以看出,在没合并之前,是不会有分叉的。其实合并也是没有分叉的,禁用Fast forward模式其实是合并的分支前进两次(因为多了一次commit),git显示分叉只是方便理解和直观的看见,如图:
然后,在dev分支上创建bug分支,查看分支:
$ git log --graph
* commit 70124a11f30e6cdcaca90bb2ba173ccf8f8bf20c (HEAD -> bug, dev)
| Author: *
| Date: Mon Jul 13 14:50:53 2020 +0800
|
| dev have a branch
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
可以发现,在创建分支的时候,其实新建分支和原分支在一起(即:指针指向一个地方,然后head指向新建的分支),大致就是这个情况:
后面的区别就是,当新建分支被修改的时候,head会和bug一起移动,而其他的都停留在原地!
再次修改bug分支并保存,查看分支:
$ git log --graph
* commit b81c466b161c057940dea59546b39b3774779739 (HEAD -> bug)
| Author: *
| Date: Mon Jul 13 14:54:52 2020 +0800
|
| bug have a branch
|
* commit 70124a11f30e6cdcaca90bb2ba173ccf8f8bf20c (dev)
| Author: *
| Date: Mon Jul 13 14:50:53 2020 +0800
|
| dev have a branch
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
这里其实就可以发现,其实每次的提交,即把工作区内容提交到版本,就会使该版本的指针和head前移,从而和其它版本分开。如图:
这里菜鸟是想直接在bug版本合并dev版本,这里就会发现一个问题:
$ git merge --no-ff -m "bug is after dev" dev
Already up to date.
这里的原因就是bug是版本中最新的(即:在整个git链上是最前面的一个),所以报错:
然后菜鸟又尝试直接在bug分支上删除bug分支,这里会报错:
$ git branch -d bug
error: Cannot delete branch 'bug' checked out at 'E:/Git_warehouse'
解决办法:
此错误是在git删除分支时报的错误,删除分支时,当前分支不能停留在要删除的分支上,要切换到其他任意分支,再去删除目标分支。
然后菜鸟才是来删除dev分支
$ git branch -d dev
Deleted branch dev (was 70124a1).
发现这里dev根本没有合并,但是也不需要使用 branch -D 的方式。
但是,如果在master里面删除dev又必须得用 branch -D ,这又是为什么?
这是因为前面的版本没有包含后面的操作,但是后面的版本是包含前面的操作的!(记住git版本是一条直线,这就很好理解)
再次查看分支:
$ git log --graph
* commit b81c466b161c057940dea59546b39b3774779739 (HEAD -> bug)
| Author: *
| Date: Mon Jul 13 14:54:52 2020 +0800
|
| bug have a branch
|
* commit 70124a11f30e6cdcaca90bb2ba173ccf8f8bf20c
| Author: *
| Date: Mon Jul 13 14:50:53 2020 +0800
|
| dev have a branch
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
发现dev被删除了,在dev分支上干的事情,dev have a branch还在,因为删除的应该只是指针!
恢复分支
那么这样删除的可以恢复吗?git作者实在是太强,给了我们无数的后悔药!
你只要通过 git reflog 找到对应的操作就可以返回到当时的操作了!菜鸟的操作如下:
$ git reflog
b81c466 (HEAD -> bug) HEAD@{0}: reset: moving to b81c466
70124a1 HEAD@{1}: reset: moving to 70124a1
b81c466 (HEAD -> bug) HEAD@{2}: reset: moving to b81c466
b81c466 (HEAD -> bug) HEAD@{3}: checkout: moving from dev to bug
70124a1 HEAD@{4}: checkout: moving from bug to dev
b81c466 (HEAD -> bug) HEAD@{5}: commit: bug have a branch
70124a1 HEAD@{6}: checkout: moving from dev to bug
70124a1 HEAD@{7}: commit: dev have a branch
4165a59 (master) HEAD@{8}: checkout: moving from master to dev
4165a59 (master) HEAD@{9}: merge dev: Fast-forward
8002fa2 HEAD@{10}: checkout: moving from dev to master
4165a59 (master) HEAD@{11}: commit: add merge2
8002fa2 HEAD@{12}: checkout: moving from master to dev
8002fa2 HEAD@{13}: merge dev: Merge made by the 'recursive' strategy.
adc26a9 HEAD@{14}: checkout: moving from dev to master
fa1517e HEAD@{15}: commit: add merge
adc26a9 HEAD@{16}: checkout: moving from master to dev
adc26a9 HEAD@{17}: commit (merge): conflict fixed
6edf4c3 HEAD@{18}: commit: & simple
asus@X MINGW64 /e/Git_warehouse (bug)
$ git branch dev HEAD@{4}
asus@X MINGW64 /e/Git_warehouse (bug)
$ git branch
* bug
dev
master
asus@X MINGW64 /e/Git_warehouse (bug)
$ git switch dev
Switched to branch 'dev'
注意:这里HEAD@{4}也可以用版本号代替!每次删除分支都会出现一个版本号,eg:
$ git branch -D bug
Deleted branch bug (was b81c466).
这里的b81c466就是的!
然后真的恢复了,bug.txt自己消失了!
大家应该可以看出,git是版本越新的的HEAD就越小!其实菜鸟在找到这个方法之前还用了 git reset --hard 版本号 的方式恢复过,发现其它都恢复了,但是分支指针没有恢复!
这里具体可以看该博客 Git删除分支/恢复分支
还有如果版本号不对或者HEAD@{}写错了的情况,见最下面!
产生分叉
这里菜鸟又试了一下,回到master分支,然后再创建一个feature分支并修改提交,然后在三个分支下查看 git log --graph ,结果如下:
asus@x MINGW64 /e/Git_warehouse (bug)
$ git log --graph
* commit 284f5e18eaef986de747c8273f6527a89e7ac61c (HEAD -> bug)
| Author: *
| Date: Mon Jul 13 20:20:17 2020 +0800
|
| add bug
|
* commit d6b76586ed2682b163b2a47983de1c2ba5ff39f8 (dev)
| Author: *
| Date: Mon Jul 13 20:17:22 2020 +0800
|
| add dev
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
asus@x MINGW64 /e/Git_warehouse (dev)
$ git log --graph
* commit d6b76586ed2682b163b2a47983de1c2ba5ff39f8 (HEAD -> dev)
| Author: *
| Date: Mon Jul 13 20:17:22 2020 +0800
|
| add dev
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
asus@x MINGW64 /e/Git_warehouse (feature)
$ git log --graph
* commit ab2852c7230f975c020f99152da23cda4a39b4bd (HEAD -> feature)
| Author: *
| Date: Mon Jul 13 20:54:40 2020 +0800
|
| add feature befor dev
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
这种在同一个节点创建多个分支就会产生分叉!类似下图:
如果接下来在featur上创建try分支呢?大致情况就是这样:
反正只要不在同一个节点创建多个分支,就不会产生分叉!
这时菜鸟又在dev后面创建dev2分支,结果如下:
asus@x MINGW64 /e/Git_warehouse (dev2)
$ git log --graph
* commit 04714739727f5fc679745d729ef42ddcc2fd8503 (HEAD -> dev2)
| Author: *
| Date: Mon Jul 13 21:35:59 2020 +0800
|
| add dev2
|
* commit d6b76586ed2682b163b2a47983de1c2ba5ff39f8 (dev)
| Author: *
| Date: Mon Jul 13 20:17:22 2020 +0800
|
| add dev
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
asus@x MINGW64 /e/Git_warehouse (bug)
$ git log --graph
* commit 284f5e18eaef986de747c8273f6527a89e7ac61c (HEAD -> bug)
| Author: *
| Date: Mon Jul 13 20:20:17 2020 +0800
|
| add bug
|
* commit d6b76586ed2682b163b2a47983de1c2ba5ff39f8 (dev)
| Author: *
| Date: Mon Jul 13 20:17:22 2020 +0800
|
| add dev
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
很明显证明了菜鸟的结论,这时类似于:
一个分叉上的某个版本要删除另一个分叉上未合并的分支,必须用 branch -D 才行!
删除feature分支,try分支不会被删除,毕竟删除的只是指针!删除try之后,这个分叉上的才算完全删除,感觉git能让我们恢复,那就一定是没有删除文件,只是删除指针!
恢复分支写错版本号
(这里是菜鸟7月14号补充的,这时候版本和上面不一样了,是最底下的那一种,而且还删了不少,这里只是说明版本号不对的问题,不必纠结)
菜鸟试了一下不用对应的版本号或者HEAD版本!发现分支确实回来了,但是回错地方了,相当于在你写的版本的地方新建了一个分支(即:bug分支上的文件并没有回来)!
asus@x MINGW64 /e/Git_warehouse (master)
$ git reflog
4165a59 (HEAD -> master) HEAD@{0}: checkout: moving from dev2 to master
0471473 (dev2) HEAD@{1}: checkout: moving from master to dev2
4165a59 (HEAD -> master) HEAD@{2}: checkout: moving from bug to master
284f5e1 HEAD@{3}: checkout: moving from dev2 to bug
0471473 (dev2) HEAD@{4}: checkout: moving from master to dev2
4165a59 (HEAD -> master) HEAD@{5}: checkout: moving from bug to master
284f5e1 HEAD@{6}: checkout: moving from dev2 to bug
0471473 (dev2) HEAD@{7}: commit: add dev2
d6b7658 HEAD@{8}: checkout: moving from dev to dev2
d6b7658 HEAD@{9}: checkout: moving from try to dev
185a9de (try) HEAD@{10}: commit: add try after feature
ab2852c HEAD@{11}: checkout: moving from feature to try
ab2852c HEAD@{12}: checkout: moving from dev to feature
d6b7658 HEAD@{13}: checkout: moving from bug to dev
284f5e1 HEAD@{14}: checkout: moving from feature to bug
ab2852c HEAD@{15}: commit: add feature befor dev
4165a59 (HEAD -> master) HEAD@{16}: checkout: moving from master to feature
asus@X MINGW64 /e/Git_warehouse (master)
$ git branch
dev2
* master
try
asus@X MINGW64 /e/Git_warehouse (master)
$ git branch bug 284f5e1(这是正确的版本号)
asus@X MINGW64 /e/Git_warehouse (master)
$ git switch bug
Switched to branch 'bug'
asus@X MINGW64 /e/Git_warehouse (bug)
$ git log --graph
* commit 284f5e18eaef986de747c8273f6527a89e7ac61c (HEAD -> bug)
| Author: *
| Date: Mon Jul 13 20:20:17 2020 +0800
|
| add bug
|
* commit d6b76586ed2682b163b2a47983de1c2ba5ff39f8
| Author: *
| Date: Mon Jul 13 20:17:22 2020 +0800
|
| add dev
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
|
* commit 8002fa2e223018c9858685f96966bfc1f8fc3250
asus@X MINGW64 /e/Git_warehouse (bug)
$ git switch master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 6 commits.
(use "git push" to publish your local commits)
asus@X MINGW64 /e/Git_warehouse (master)
$ git branch -D bug
Deleted branch bug (was 284f5e1).
asus@X MINGW64 /e/Git_warehouse (master)
$ git branch bug 0471473
asus@X MINGW64 /e/Git_warehouse (master)
$ git switch bug
Switched to branch 'bug'
asus@X MINGW64 /e/Git_warehouse (bug)
$ git log --graph
* commit 04714739727f5fc679745d729ef42ddcc2fd8503 (HEAD -> bug, dev2)
| Author: *
| Date: Mon Jul 13 21:35:59 2020 +0800
|
| add dev2
|
* commit d6b76586ed2682b163b2a47983de1c2ba5ff39f8
| Author: *
| Date: Mon Jul 13 20:17:22 2020 +0800
|
| add dev
|
* commit 4165a59cf8e4d6434f81231481fbb099141d0741 (master)
| Author: *
| Date: Sun Jul 12 17:38:45 2020 +0800
|
| add merge2
|
* commit 8002fa2e223018c9858685f96966bfc1f8fc3250
asus@X MINGW64 /e/Git_warehouse (bug)
$ git branch
* bug
dev2
master
try
其实这是个复杂的事情,所以删除分支前一定要确保已经合并了,或者真的不要了,因为删除分支给的版本号在关闭后就没了,然后删除分支又不会被记录到reflog里面!
这里菜鸟找到一个小妙招,其实要找删除分支对应的版本,就是找你reflog里面记录的你跳转到该删除分支的那条命令就行,前面的版本号就是该删除分支的版本号!