note/git-core-concept

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 的指向不会改变。

这个操作不会更改历史。

未指定文件

  1. 当前工作区所在的分支通过 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
  2. 可用于撤销更改

    git checkout HEAD -- 更改的文件
    git checkout -- 更改的文件 # 未指定分支时默认为 HEAD
  3. 我想浏览某一次提交时版本库的文件,导出某个文件,或做一些实验。

    git checkout 587a2e
    graph LR
    master -.-> b
    a[587a2e] --> b[2eb7f3]
    b --> c[9a8fe3]
    c --> d[46ab8d]
    develop -.-> d
    HEAD -.-> a

    这时 HEAD 是 “游离” 的(detached),此时进行的提交在切换分支时将非永久地丢失(知道 sha 码时可以找回)。

指定了文件

  1. 某次提交的某个文件的更改不是很好,我想把那个文件恢复到那个提交之前。(以便接下来的修改)

    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>]

About Me