git实战-5、理解HEAD头指针
前言
当我们切换到其他提交点时候,出现’detached HEAD’ state,也就叫分离头指针状态,
该状态是项目当前脱离当前分支Head commit,处于一种无分支的状态,可以在checkout到commit后,为该状态使用git checkout -b new_branch_name 创建一个分支。
假如在还没为状态下创建分支,进行commit,该commit是不安全的,当切到其他分支(比如master分支)Head commit状态,这是危险的,容易丢失代码,没有分支的commit会在一段时间内被git的丢弃。
[app@iz8vb2knpxzlk1syb8dy3cz my-resp]$ git checkout 8c11d13836
Note: checking out '8c11d13836'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at 8c11d13... test3
##命令总结
#处于分离头结点状态,为当前状态创建一个分支
git checkout -b new_branch_name
#处于正常状态,从branch_name分支创建一个分支new_branch_name
git checkout -b new_branch_name branch_name
#为当前状态创建一个分支
git checkout -b new_branch_name
那分离头指针在使用中, 到底有哪些具体的适用地点呢?
1、如果临时想基于某个commit做变更,试试新方案是否可行,就可以采用分离头指针的方式。测试后发现新方案不成熟,直接reset回其他分支即可,省去了建、删分支的麻烦,git会忽略管理这个没有分支commit。
2、进行到某个commit,试试新方案,为该commit建立新的branch,可以进行特性开发。
3、分离头指针对应的commit,你如果认为有用需要保留,那就用新分支把它保留。
4、如果当下无master分支,可以在分离头指针状态下,git checkout -b master HEAD
实战测试
#初始化git仓库
1、git init detach_head_test
#进入到仓库
2、cd detach_head_test/
#创建readme1.md文件,和
3、echo "123" > readme1.md
#并添加git
git add readme.md
#commit修改
git commit -m'test1'
#创建readme2.md文件
4、echo "123" > readme2.md
#添加git
git add readme2.md
#commit修改
git commit -m'test2'
# 查看当前提交记录
5、git log
# 切换到teset1 commit状态,进行分离头结点状态,git提醒创建分支
6、git checkout 938d887
# 该状态,创建test3 commit
7、echo "123" > readme3.md
git add readme3.md
git commit -m'test3'
#查看状态
8、git log
# 切换master HEAD commit点,出现警告,是否为分离头结点状态下commit创建分支
9、git checkout master
10、为该分离头结点状态下commit创建分支,如不创建git将会在一段时间丢弃该commit
git branch new_branch_name a6ffbc5
# 查看所有分支
11、git branch -vv
以下是操作记录:
[app@iz8vb2knpxzlk1syb8dy3cz git]$ git init detach_head_test
Initialized empty Git repository in /data/app/git/detach_head_test/.git/
[app@iz8vb2knpxzlk1syb8dy3cz git]$ ls
detach_head_test my-resp watch_git_object
[app@iz8vb2knpxzlk1syb8dy3cz git]$ cd detach_head_test/
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ ls
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ echo "123" > readme.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git add readme.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git commit -m'test1'
[master (root-commit) 938d887] test1
1 file changed, 1 insertion(+)
create mode 100644 readme.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ echo "123" > readme2.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git add readme2.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git commit -m'test2'
[master 7d592f9] test2
1 file changed, 1 insertion(+)
create mode 100644 readme2.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git log
commit 7d592f9454632242047a1d7b7bce2642c3fcd194
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:49 2019 +0800
test2
commit 938d88743c5cab96b895549699467afc3a460684
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:24 2019 +0800
test1
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git checkout 938d887
Note: checking out '938d887'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.
If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:
git checkout -b new_branch_name
HEAD is now at 938d887... test1
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ ls
readme.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ echo "123" > readme3.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git add readme3.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git commit -m'test3'
[detached HEAD a6ffbc5] test3
1 file changed, 1 insertion(+)
create mode 100644 readme3.md
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git commit -m'test3'git log
error: pathspec 'log' did not match any file(s) known to git.
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ ^C
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git commit -m'test3'
# HEAD detached from 938d887
nothing to commit, working directory clean
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git log
commit a6ffbc588b3df38b5558d20c140bb545ef2b6dfd
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:22:50 2019 +0800
test3
commit 938d88743c5cab96b895549699467afc3a460684
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:24 2019 +0800
test1
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git checkout master
Warning: you are leaving 1 commit behind, not connected to
any of your branches:
a6ffbc5 test3
If you want to keep them by creating a new branch, this may be a good time
to do so with:
git branch new_branch_name a6ffbc5
Switched to branch 'master'
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git branch new_branch_name a6ffbc5
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git -vv
Unknown option: -vv
usage: git [--version] [--help] [-c name=value]
[--exec-path[=<path>]] [--html-path] [--man-path] [--info-path]
[-p|--paginate|--no-pager] [--no-replace-objects] [--bare]
[--git-dir=<path>] [--work-tree=<path>] [--namespace=<name>]
<command> [<args>]
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git branch -vv
* master 7d592f9 test2
new_branch_name a6ffbc5 test3
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git log
commit 7d592f9454632242047a1d7b7bce2642c3fcd194
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:49 2019 +0800
test2
commit 938d88743c5cab96b895549699467afc3a460684
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:24 2019 +0800
test1
项目gitk状态图
使用gitk --all 命令查看
Head的作用和标识符号作用
Head头结点作用是,指代.git/HEAD的执行,.git/HEAD 指向 .git/refs/heads/xxx分支,xxx分支其实是当前分支一个commit类型的提交信息。
补充:
始讲HEAD的使用,以及PARENT符号^和~
1 一个节点,可以包含多个子节点(checkout 出多个分支)
2 一个节点可以有多个父节点(多个分支合并)
3 是~都是父节点,区别是跟随数字时候,2
是第二个父节点,而~2是父节点的父节点
4 ^和~可以组合使用,例如 HEAD~2^2
使用git diff 比较两个commit的差异,可以参考链接
https://github.com/gotgit/gotgit/blob/master/01-meet-git/010-scm-history.rst
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git checkout -b fix_readme
Switched to a new branch 'fix_readme'
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git status
# On branch fix_readme
nothing to commit, working directory clean
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git log
commit 7d592f9454632242047a1d7b7bce2642c3fcd194
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:49 2019 +0800
test2
commit 938d88743c5cab96b895549699467afc3a460684
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:24 2019 +0800
test1
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git log -n1
commit 7d592f9454632242047a1d7b7bce2642c3fcd194
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:49 2019 +0800
test2
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ cat .git/HEAD
ref: refs/heads/fix_readme
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ cat .git/refs/heads/fix_readme
7d592f9454632242047a1d7b7bce2642c3fcd194
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git cat-file -t 7d592f9454632242047a1d7b7bce2642c3fcd194
commit
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git log
commit 7d592f9454632242047a1d7b7bce2642c3fcd194
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:49 2019 +0800
test2
commit 938d88743c5cab96b895549699467afc3a460684
Author: globaltest <globaltest@xx.com>
Date: Tue Feb 26 13:20:24 2019 +0800
test1
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git diff 938d88743 7d592f9454
diff --git a/readme2.md b/readme2.md
new file mode 100644
index 0000000..190a180
--- /dev/null
+++ b/readme2.md
@@ -0,0 +1 @@
+123
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git diff HEAD HEAD~1
diff --git a/readme2.md b/readme2.md
deleted file mode 100644
index 190a180..0000000
--- a/readme2.md
+++ /dev/null
@@ -1 +0,0 @@
-123
[app@iz8vb2knpxzlk1syb8dy3cz detach_head_test]$ git diff HEAD HEAD^
diff --git a/readme2.md b/readme2.md
deleted file mode 100644
index 190a180..0000000
--- a/readme2.md
+++ /dev/null
@@ -1 +0,0 @@
-123