Git 核心概念
<>
:参数
[]
:可选参数
比较熟练使用 git 后想着要写这篇笔记很久了。世界是物质的,我们的记忆不过是大脑内的一些连比较接和电状态而已,谁也不能保证自己不会意外失忆。
git 是一个版本管理工具(VCS)。
工作区 版本库
工作区就是你在路径下看到的内容。git 会将工作区的各个历史版本按照你的要求储存在隐藏的 .git
路径下,这就是版本库。
git init # 以当前为根路径,新建 git 仓库
commit 提交(作为名词)
git 通过 commit 储存各个版本之间的差异。每个 commit 都有一串十六进制数( sha )来标识。放心,这串随机数很长,重号是几乎不可能的。除此以外每个 commit 还有备注信息。
add 暂存
将工作区的更改(或新文件)提交到版本库之前,要把更改先放到一个名为暂存区的地方。
git add 233.txt # 将 233.txt 的更改储存到暂存区
git add ./directory/ # 将 directory 路径中所有文件的更改放到暂存区
git add . # 将当前路径下所有文件的更改放到暂存区
撤销更改
对于还没有进入版本库(未被追踪)的文件,直接删除它即可(手动删除比较麻烦的话可以用 git clean
)。已被追踪的文件可以使用 checkout 撤销回暂存区的状况。
git checkout -- 更改的文件或路径
已经暂存的更改无法撤销,必须首先:
取消暂存
使用 reset 可以取消暂存。
git reset -- 已经暂存的文件
status 状态
查看那些文件被更改了、那些更改被暂存了、现在在那个分支上。
git status
git status -s # 简略表示
diff
git diff 先前的提交 后面的提交 -- 文件
若未指定提交则对比暂存区和工作区。
--cached
: 显示已暂存的更改与版本库HEAD
的区别。
commit 提交(作为动词)
将暂存区的文件提交到版本库。
git commit -m 'This is a commit message'
git commit -v # verbose, 在编辑器中显示所有更改,可检查后再提交
log 日志
使用 log 查看提交历史。一些参数:
--abbrev-commit 简略 sha 码
--graph 显示 log 图
--pretty=
oneline 单行显示
format:"" 格式化显示
我喜欢的配置:
[alias]
lg = log --color --graph --pretty=format:'%C(auto)%h%Creset -%C(auto)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit
branch 分支
branch 是开发过程中的枝条,commit 必须依附在 branch 上,否则就会从版本库中非永久地消失。各个版本的 commit 通过 branch 串在一起,就形成了当前的版本内容。
一个代码库可以有多个 branch,默认分支名为 master
。
a^
表示 a
分支指向的提交之前的那个提交。
假设现在的版本库如图所示。
graph LR master -.-> b a[587a2e] --> b[2eb7f3] b --> c[9a8fe3] c --> d[46ab8d] develop -.-> d HEAD -.-> master
checkout
git checkout <branch/commit> -- <file>...
有两个意思:
- 若没有指定文件,则把
HEAD
切换到那个提交或分支上去。 - 若指定了文件,则把文件更改为那个(提交或分支)的内容,然后暂存。
HEAD
的指向不会改变。
这个操作不会更改历史。
未指定文件
当前工作区所在的分支通过
HEAD
指示,可以通过git checkout <branch>
切换 HEAD 指向的分支。git checkout develop
graph LR master -.-> b a[587a2e] --> b[2eb7f3] b --> c[9a8fe3] c --> d[46ab8d] develop -.-> d HEAD -.-> develop
可用于撤销更改:
git checkout HEAD -- 更改的文件 git checkout -- 更改的文件 # 未指定分支时默认为 HEAD
我想浏览某一次提交时版本库的文件,导出某个文件,或做一些实验。
git checkout 587a2e
graph LR master -.-> b a[587a2e] --> b[2eb7f3] b --> c[9a8fe3] c --> d[46ab8d] develop -.-> d HEAD -.-> a
这时
HEAD
是 “游离” 的(detached),此时进行的提交在切换分支时将非永久地丢失(知道 sha 码时可以找回)。
指定了文件
某次提交的某个文件的更改不是很好,我想把那个文件恢复到那个提交之前。(以便接下来的修改)
git checkout 587a2e^ -- 文件
checkout -b 创建并切换分支
git checkout -b <branch_name>
merge 合并
各个 branch 之间可以通过几个 commit 交叉,这就是合并。通过 git merge <branch>
可将分支合并到当前分支处。
快进合并(默认)
git merge develop
graph LR master[master] -.-> d a[587a2e] --> b[2eb7f3] b --> c[9a8fe3] c --> d[46ab8d] develop[develop] -.-> d HEAD[HEAD] -.-> master
非快进合并
在无法执行快进或标明 --no-ff
时发生。它会把 develop 分支上所做的更改添加到 master 上,然后新建一个提交。
git merge --no-ff develop
graph LR master -.-> f a[587a2e] --> b[2eb7f3] b --> f[66666e] b --> c[9a8fe3] c --> d[46ab8d] d --> f develop -.-> d HEAD -.-> master
这时称 66666e
有两个父级。
reset
将当前分支和 HEAD
移动到某个提交或某个分支指向的提交上。 这个操作会改变历史 。
git reset <branch/commit> -- <file>... [--hard]
remote 远程
远程仓库用于解决团队协作时,“拷来拷去,最后版本混乱”的问题。remote 可以将把分支推送到任意一台计算机的任意一个仓库中,只要它也安装了 git,你有写入权限。但更常见的方式是将一台计算机作为中介、全天开机,供所有成员访问。
# GitHub 是全球影响力最大的 git 代码库托管平台
git remote add origin git@github.com:用户名/仓库名 # 通过 ssh
git remote add origin https://github.com/用户名/仓库名 # 通过 https
push 推送
push 的单位是 branch。
git push origin master # 将 master 分支的更新推送到远程仓库。
git push -u origin master # 推送 master,并把 origin/master 和本地的 master 关联起来,称为本地 master 的 upstream 。
git push # 将有 upstream 的分支推送到远程仓库。
git push origin <local_br>:<remote_br> # 将本地的 <local_br> 分支推送到远程的 <remote_br> 分支中。
git push origin :<remote_br> # <local_br> 为空,远程仓库将会删掉 <remote_br> 分支。
fetch 获取
从远端获取分支的更新,放在 origin/*
分支中。
pull 获取并合并
git pull origin <remote_br>[:<local_br>]