摘自『Pro Git』以及 Git手册
仅用于本人理解和查阅。不全之处,日后补充。
Git分支
Git每次提交可以简单理解为创建一个当前提交文件的快照,并且当前的提交对象包含一个指向上次提交对象的指针。但是单纯创建分支并没有产生提交。当你从新分支的新版本回滚时,是将新的提交对象替换为了旧版本的提交对象。
Git分支实质上是包含所指对象校验和(长度为40的SHA-1值字符串)的文件
Q:提交记录多了之后,每个版本的快照会不会占用很多空间?
A:如果是没修改过的文件,新提交里的快照似乎也只是用一个指针指向原本的文件罢了;如果每个版本都对许多文件进行了大量的修改,那占用空间增多是无法避免的。
Q:那么每个版本的文件快照(提交对象)是什么东西?
忽略文件
可在git仓库目录中的.gitignore
文件中,设置忽略的文件,如
1
2
*.[oa]
*~
将会忽略所有以.o
或.a
以及~
结尾的文件。
格式规范如下:
- 忽略所有空行和以
#
开头的行 - 可以使用标准的glob模式(简化的正则表达式)匹配
- 模式匹配可以以
/
开头防止递归 - 可以以
/
结尾指定目录 - 可以在模式前加
!
取反
*
匹配0个或任意个字符;
[abc]
匹配方括号中的一个字符;
[0-9]
使用短划线分割两个字符则匹配两个字符范围内的任意字符(一个);
使用两个星号**
匹配任意中间目录, 如a//**/z
可以匹配a/z
, a/b/z
或a/b/c/z
1
2
3
4
5
6
7
8
# ignore all files in the build/ directory
build/
# ignore doc/notes.txt, but not doc/server/arch.txt
doc/*.txt
# ignore all .pdf files in the doc/ directory
doc/**/*.pdf
Git HEAD指针
HEAD^
==> HEAD
的父指针
HEAD~2
==> HEAD
的祖父指针,相当于HEAD^^
HEAD^2
==> HEAD
的第二父提交,只在合并分支的提交中可以使用(因为有不止一个父提交,第一父提交是合并时所在的分支,第二父提交是合并进来的分支)
Command
-
git diff
显示尚未暂存的改动与暂存区文件快照之间的差别
-
git rm
1 2 3
# 不加参数时,从暂存区和工作区移除文件。匹配多个文件使用 * 号时,需要加反斜杠\ --cached # 仅从暂存区移除,在工作区保留
-
git mv
文件改名
1
git mv oldName.md newName.md
-
git log
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
-p # 显示每次提交的内容差异 -2 # 显示最近两条提交记录 --since=2.weeks --since="2019-10-01" -S # 显示添加或者移除了某些特殊字符串的提交 -Sfunction_name # 查找添加/移除了"function_name"的提交 --pretty # =oneline # =format:"%h " --oneline *--*----*---*---master \ ----*---*---exp master..exp # 查看在exp分支而不在master分支中的提交 # 在分支引用前加^或--not指明不希望包含在内的分支,因此上式等价于 exp ^master # 或 exp --not master --left-right master...exp # 被master和exp其中一个包含但不是二者共有的提交 # --left-right将标识该提交属于左/右(master/exp)
-
git checkout
1 2 3 4 5 6
git checkout -- <filename> # 用某次提交的文件来覆盖暂存区和工作区的文件,所以会丢失工作区中的修改 # 请慎重使用 -b <branch name> # 创建并将HEAD移动到一个新分支
-
git commit
1 2 3
--amend # 将修改合并到上一次commit中,类似做了rebase操作,会修改SHA-1的校验和 #(所以如果push到远端了就不要使用。why?远程仓库不能一起修改吗)
-
git remote
1 2 3
https git:// git@github
-
git fetch
从远程仓库拉取数据,但是不合并。若希望拉取数据同时合并请使用
pull
。p80: 抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本,只有一个不可修改的指针
Q:到底抓取了什么东西下来?
-
git stash
暂存未完成并且不想提交的改动
1 2 3 4 5 6 7 8 9 10 11 12 13
git stash / git stash save # 暂存 git stash list # 查看栈中的暂存 git stash apply ( stash@{2} ) # 不指定则默认为0 git stash pop # 应用暂存,然后丢弃 git stash drop ( stash@{2} ) # 丢弃指定的暂存
-
git reset
1 2 3 4 5 6 7 8 9 10
--soft # 只移动HEAD指针 --mixed # 移动HEAD指针,并且回滚暂存区。因此会回到那次提交之前的状态(如果之后你对工作区有改动的话) --hard --merge # 移动HEAD指针,并且改变暂存区和工作区 # 目前需要的回滚通常要改变工作区,所以这两个选项会用的比较多
-
git checkout
1 2 3 4 5
git checkout [branch] # 类似git reset --hard [branch],并且不会移动分支的指针 git checkout [branch] filename # 类似git reset --hard,不移动HEAD指针,修改暂存区,不同的是会覆盖工作区中的文件
回想一下,
git reset --mixed
移动HEAD指针, 但是同样我们也可以用--soft
把HEAD移动到想要的位置. -
git push
1 2 3 4 5 6 7 8 9
-f --force # --force-with-lease --force-with-lease=<refname> --force-with-lease=<refname>:<expect> # 如果远程仓库里的记录不是当前要推送提交的上游分支(比如使用了rebase) # git push默认拒绝这样的操作。此时需要--force-with-lease选项。
-
git pull
跟踪分支
从一个远程分支checkout一个本地分支会在本地创建“跟踪分支”,它跟踪的分支叫做“上游分支”
在跟踪分支上运行git pull
能够自动抓取上游分支并且合并到当前的跟踪分支。
可以使用
1
2
3
4
5
6
7
8
git checkout --track origin/serverfix
# 将serverfix设为跟踪分支
git checkout -b sf origin/serverfix
# 将sf设为跟踪分支
git branch -u/--set-upstream-to origin/master
# 将当前分支的上游分支修改为origin仓库的master分支
(TODO)merge, rebase
-
–depth=1 ->断点续传?
1 2
# e.g. git clone --depth=1 --single-branch --branch fuck-branch url