上一篇git 基本原理对git的使用以及文件分布已经有了一个整体的了解。
本篇将对工作中常用的一些git 操作命令的操作进行总结归纳,方便今后查阅。
当我们想要切换分支的时候,无意中点了commit的对象id,然后在其分支上做了大量的变更。
这个时候当前分离头指针的状态就是没有分支的状态, 此时如果你切换到其他的分支继续进行开发的时候很有能导致之前在分离头指针的状态下做的大量的变更都被丢弃掉了。
过程如下:
Baron@MacBook-Progit_learning % git checkout bce2f242
注意:正在切换到 'bce2f242'。
您正处于分离头指针状态。您可以查看、做试验性的修改及提交,并且您可以在切换
回一个分支时,丢弃在此状态下所做的提交而不对分支造成影响。
如果您想要通过创建分支来保留在此状态下所做的提交,您可以通过在 switch 命令
中添加参数 -c 来实现(现在或稍后)。例如:
git switch -c <新分支名>
或者撤销此操作:
git switch -
通过将配置变量 advice.detachedHead 设置为 false 来关闭此建议
HEAD 目前位于 bce2f24 modify on temp branch
Baron@MacBook-Progit_learning % echo "222" > readme
Baron@MacBook-Progit_learning % git add readme
Baron@MacBook-Progit_learning % git commit -m"add readme file"
[分离头指针 286afae] add readme file
1 file changed, 1 insertion(+)
create mode 100644 readme
Baron@MacBook-Progit_learning % git log
commit 286afae9cb98199213a546aa2d087a16cc63e391 (HEAD)
Author: BaronStack <[email protected]>
Date: Fri Jul 3 19:38:46 2020 +0800
add readme file
commit bce2f2428649f640d98d4fbb011084c53c87fa25 (temp)
Author: BaronStack <[email protected]>
Date: Sat Jun 27 20:34:01 2020 +0800
modify on temp branch
commit b360e56b39a5d605918816ea4dc07d61e93b12f8
Author: BaronStack <[email protected]>
Date: Sat Jun 27 20:27:21 2020 +0800
mod testfile
commit 30a71408576f421909d05cdd424703b8866dd943
Author: BaronStack <[email protected]>
Date: Sat Jun 27 20:26:51 2020 +0800
add test_file
Baron@MacBook-Pro git_learning % git checkout temp
警告:您正丢下 1 个提交,未和任何分支关联:
286afae add readme file
如果您想要通过创建新分支保存它,这可能是一个好时候。
如下操作:
git branch <新分支名> 286afae
切换到分支 'temp'
Baron@MacBook-Pro git_learning % git branch seprate 286afae
Baron@MacBook-Pro git_learning % git branch -a
master
seprate
* temp
Baron@MacBook-Pro git_learning % git checkout seprate
切换到分支 'seprate'
Baron@MacBook-Pro git_learning % git ls
readme test_file
此时再切换回去的时候已经能够发现在分离头指针状态下的变更(创建的readme文件)已经能够看到了。先描述一下HEAD 指向的含义,每一次git log查看的时候都会发现最新的commit都会有一个HEAD来指向对应的分支或者就是一个单独的HEAD(分离头指针的情况)
#正常的分支
commit 286afae9cb98199213a546aa2d087a16cc63e391 (HEAD -> seprate)
#分离头指针的情况
commit 286afae9cb98199213a546aa2d087a16cc63e391 (HEAD)
查看.git文件中的HEAD文件,可以看到具体的内容,ref指向一个文件
Baron@MacBook-Pro git_learning % cat .git/HEAD
ref: refs/heads/seprate
查看指向的文件内容,以及类型,可以发现最终的指向还是一个commit类型
Baron@MacBook-Pro git_learning % cat .git/refs/heads/seprate
286afae9cb98199213a546aa2d087a16cc63e391
Baron@MacBook-Pro git_learning % git cat-file -t 286afae9c
commit
所以我们想要对比不同变更的内容差异,即可通过如下方式
对比不同的commit id,git diff 286afae9 bce2f2428
Baron@MacBook-Pro git_learning % git diff 286afae9 bce2f2428
diff --git a/readme b/readme
deleted file mode 100644
index c200906..0000000
--- a/readme
+++ /dev/null
@@ -1 +0,0 @@
-222
对比HEAD和其父亲的变更, 直接通过 git diff HEAD HEAD~1
或者git diff HEAD HEAD^1
Baron@MacBook-Pro git_learning % git diff HEAD HEAD^1
diff --git a/readme b/readme
deleted file mode 100644
index c200906..0000000
--- a/readme
+++ /dev/null
@@ -1 +0,0 @@
-222
对比HEAD 和其父亲的父亲 的变更,直接通过git diff HEAD HEAD~2
或者git diff HEAD HEAD^^
Baron@MacBook-Pro git_learning % git diff HEAD HEAD^^
diff --git a/readme b/readme
deleted file mode 100644
index c200906..0000000
--- a/readme
+++ /dev/null
@@ -1 +0,0 @@
-222
diff --git a/test_file b/test_file
index d8124e2..58c9bdf 100644
--- a/test_file
+++ b/test_file
@@ -1,2 +1 @@
111
-22
git branch -d branch_name
该情况适用于删除的分支没有新的变更才行,有变更的话会报错git branch -D branch_name
使用-d删除不掉的时候可以使用-D 来删除大体过程如下
Baron@MacBook-Pro git_learning % git branch -av
66389211 286afae add readme file
master ade6638 add readme file
* seprate 286afae add readme file
temp bce2f24 modify on temp branch
Baron@MacBook-Pro git_learning % git branch -d 66389211
已删除分支 66389211(曾为 286afae)。
Baron@MacBook-Pro git_learning % git branch -d temp
已删除分支 temp(曾为 bce2f24)。
Baron@MacBook-Pro git_learning % git branch -d seprate #当前工作目录处于被删除的分支之上,需要更改工作目录
error: 无法删除检出于 '/Users/zhanghuigui/Desktop/work/work_file/mind-map/git_learning' 的分支 'seprate'。
Baron@MacBook-Pro git_learning % git checkout master
切换到分支 'master'
Baron@MacBook-Pro git_learning % git branch -d seprate
error: 分支 'seprate' 没有完全合并。
如果您确认要删除它,执行 'git branch -D seprate'。
Baron@MacBook-Pro git_learning % git branch -D seprate
已删除分支 seprate(曾为 286afae)。
Baron@MacBook-Pro git_learning % git branch -av #删除完成,仅剩下一个分支
* master ade6638 add readme file
git commit --amend
使用vim编辑修改即可
修改之后
git rebase -i commitid
这里的commit id需要填写我们要修改的旧的commit的父亲commit id
保存之后会进入如下页面
修改完成后,git log
查看,即能够看到修改的结果已经生效
git rebase -i commitid
这里的commit id 仍然是所有commit的父亲commit id
我们想要合并如下三个commit信息
则使用其父亲commit的id信息 git rebase -i 9e5a0d1
保存后跳转到message信息的编辑页面
最终已经完成了指定message信息的合并
gitk --all
可视化查看当前commit信息
仍然使用git rebase -i commitid
对commit记录进行合并,合并的方式和之前连续的方式一样,只不过修改的时候修改对应的pick为s即可
git diff --cached
比较暂存取和HEAD 最新内容的差异
Baron@MacBook-Pro git_learning % echo "444" >> test_file
Baron@MacBook-Pro git_learning % git add test_file #添加到暂存区
Baron@MacBook-Pro git_learning % git diff --cached #将暂存区内容和HEAD进行比较
diff --git a/test_file b/test_file
index 58c9bdf..b8dd46c 100644
--- a/test_file
+++ b/test_file
@@ -1 +1,2 @@
111
+444
之后确认暂存区的更改是我们想要的更改,即可进行commit
git diff
默认比较工作区和暂存区的内容
git diff -- test_file
仅仅比较具体文件的工作区和暂存区文件的差异
Baron@MacBook-Pro git_learning % git diff -- test_file
diff --git a/test_file b/test_file
index b8dd46c..f5fb332 100644
--- a/test_file
+++ b/test_file
@@ -1,2 +1,3 @@
-111
+222
444
+999999
工作中有时候我们会想要将暂存区中的内容恢复到HEAD的程度,此时有可能工作区中的某一些方案更好,我们就像将暂存取中的变更全部撤销掉,恢复到和HEAD一样的,可以通过命令
git reset HEAD
恢复所有暂存区的内容到HEADgit reset HEAD -- test_file
恢复具体的文件内容到HEADBaron@MacBook-Pro git_learning % git reset HEAD
重置后取消暂存的变更:
M test_file
Baron@MacBook-Pro git_learning % git diff --cached #此时可以发现工作区和HEAD已经没有差异了
Baron@MacBook-Pro git_learning %
发现工作区的变更还不如暂存区,此时需要将工作区的内容恢复到暂存区的内容。
较为旧的git版本使用的是git checkout -- filename
,为了防止命令执行的歧义,最新的git版本已经变更为git restore filename
执行之前工作区和暂存区的信息差异
执行之后已经恢复成一样的内容了
Baron@MacBook-Pro git_learning % git restore test_file
Baron@MacBook-Pro git_learning % git diff test_file
Baron@MacBook-Pro git_learning %
这里是指我们工作中有几个commit所有相关的信息都不想要了,这个时候即可变更HEAD头指针的位置
git reset --hard commitid
PS:这条命令非常危险,如果能够确认 真的不需要当前commit之前所有的信息之后即可执行该操作,否则执行命令之后丢弃的变更就找不回来了
如下,我们想要丢弃 蓝色方框内commit之前所有commit变更内容
已经完成变更之后的log信息
git diff commitid commitid --- file
这里只需要指定不同的commit id即可完成不同commit内容的差异比较。
总共两种方法:
当我们工作中突然有了需要在HEAD指向的内容中增加一些功能, 但是我们已经在工作区中了做了大量的变更,此时为了保存我们工作区中的内容,先完成紧急任务,需要使用如下功能来完成。
git stash
暂存工作区,同时将工作区内容恢复到HEAD所指的内容git stash list
查看当前有多少个暂存的工作区,栈形式的存储结构git stash apply
从当前保存的暂存区列表中取出列表头部暂存区内容git stash pop
从当前保存的暂存区列表中取出列表头,并删除列表头我们在实际开发过程中可能只想要让git管理我们需要的源码文件,而像二进制文件,或者.o,.d文件等中间文件都不需要纳入git的版本管理之中,这个时候我们就需要维护一个只管理我们想要的文件。
.gitignore
文件就是git 中做这样的事情,我们将我们不想管理的文件按照指定的格式添加到这个文件之中即可。
PS:这里需要注意的是gitignore文件只对不在暂存区中的文件起作用,如果在添加.gitignore
之前文件已经存在于暂存区,则此时在.gitignore
去除该文件,是不会生效的,且此时的文件名必须叫做.gitignore才能够被git识别。
.gitignore文件格式如下:
*.*jnilib* #支持通配符来匹配文件
*.d-e #所有的.d文件
*.o-* #所有的.o文件
*.swp #所有的.swp文件
*~
*.vcxproj
*.vcxproj.filters
*.sln
*.cmake
.watchmanconfig
CMakeCache.txt
CMakeFiles/
build/
测试如下:
Baron@MacBook-Pro git_learning % cat .gitignore #此时忽略test文件,以及test目录下的所有文件
# test file
test
Baron@MacBook-Pro git_learning % ls -al
total 24
drwxr-xr-x 6 staff 192 7 5 12:56 .
drwxr-xr-x 10 staff 320 7 4 12:30 ..
drwxr-xr-x 15 staff 480 7 5 12:57 .git
-rw-r--r-- 1 staff 17 7 5 12:56 .gitignore
-rw-r--r-- 1 staff 8 7 5 12:06 readme
-rw-r--r-- 1 staff 9 7 5 12:40 test_file
Baron@MacBook-Pro git_learning % echo '111' >test #创建一个test文件
Baron@MacBook-Pro git_learning % ls -l
total 24
-rw-r--r-- 1 staff 8 7 5 12:06 readme
-rw-r--r-- 1 staff 4 7 5 12:59 test
-rw-r--r-- 1 staff 9 7 5 12:40 test_file
Baron@MacBook-Pro git_learning % git status
位于分支 master
无文件要提交,干净的工作区
git备份时可以用到的传输协议如下,大体分为两种:哑协议和智能协议。
其中哑协议是看不到进度的,智能协议能够看到传输进度,且智能协议性能优于哑协议。
如下使用本地协议进行备份, 其中git clone --bare
是指直接备份一个纯仓库到本地。
以下为分别使用两种本地协议进行备份。
git remote add zhineng zhinneg.repo.git
为本地配置远端的git源
当我们在本地做了变更之后,可以将本地的变更同步到远端
git push
即可
或者在远端的指定分之使用git fetch
将本地的内容拉回到远端