git - noonecare/linux GitHub Wiki

git 重要的概念

工作区

工作目录

暂存区

.git/index 文件中记录的 树对象

版本库

.git 是本地版本库,版本库记录了历史。版本库如果不带工作区,就称为 裸版本库(empty repository)

对象

.git/Objects 下的内容。Git 对象有4种。所有的对象都有一个独一无二的ID(也称hash码)。这个ID通过 SHAI 算法计算得到。

提交

提交对象,记录了两种信息:提交时的目录(树对象表示),parent提交(提交对象)。

树对象

记录了发生修改的所有blob对象,相当于一个目录。

blob对象

记录了每个文件的修改信息。

tag对象

提交 ID 不好记, tag 算是提交ID的别名,也就是说你可以给提交起个 好记的名字(这个名字常常是软件的版本号)。tag 也就是常常说的里程碑。

HEAD

.git/HEAD 文件,一般这个文件的内容是分支的名称。但是也可以是一个任意的提交 ID 或者 tag。当 .git/HEAD 文件的内容不是分支的名称时。会提示 “头指针与分支分离”。

分支 分支是一个指向提交的记号

本地分支

.git/refs/heads目录下的文件。比如master, develop 等等,你打开这些文件,这些文件的内容时分支指向的提交的 ID 。

远程分支

.git/refs/remotes/目录下保存着远程版本库。远程版本库目录下保存着远程分支,远程分支同样是个文件,每个文件的内容都是某个提交的 ID。

跟踪

分支之间的关系。这种关系写在 git 配置文件 .git/config 中。建立了跟踪关系之后,执行 git status 时显示的是暂存区和当前分支所跟踪的分支有那些改动。通过跟踪关系可以实现版本库之间的同步,简单说就是执行嗯git push 和 git pull。

日志

git 在 .git/log 文件中记录了 HEAD 以及各个分支的指向历史。

引用表达式

fast-forward: 两个分支A,B 如果 A 的所有提交都是 B 的历史提交,或者 B 的所有提交都是 A 的历史提交,那么A, B合并是 fast-forward 的。

冲突

git 可以自动合并很多冲突,当自动合并不能解决冲突时,就需要你亲自决定如何解决冲突。解决冲突时可以根据冲突信息,直接用编辑器修改文件。也可以使用 git mergetool 命令调用 可视化的工具(比如kdiff3)去解决冲突。

配置文件

配置文件 .git/config git的配置文件是ini 格式的文件。 git config 可以显示和修改配置文件。git remote 可以显示和修改配置文件中的某些值。

git 命令

下面的所有指令都可以,用 git help 查询如何使用。比如 git help add。通过查询,可以得到git 命令的准确的用法。下面,我不再重复这些内容,只是强调一下这些命令中最常用的用法。

git add 把变动添加到 index 。

git add 把 目录下的改动添加到 index。 git add -u

git commit

git commit -m

git tag 添加标签(里程碑)

git clone 克隆版本库

git clone [--bare] [--mirror]

git remote 显示/设置远程分支

git remote [-v] git remote add git remote rename git remote -d git remote set-url

git reflog

git stash

git stash git stash pop

git merge git fetch git pull git push git reset git checkout git rebase git diff git grep git cherry-pick git log git revert git clean up git mergetool git gc git add git rm

可能还会用到的一些命令有 git rev-parse git ls-file git cat-file git rev-list

引用表达式 < ref >@{< num >} 用在 git stash, git reflog 命令中。 HEAD@{< num >} 表示上 num 次 时, HEAD 的值。stash@{< num >}表示上 num 次 stash 的值。

< commit >^{< num >} commit 的第 num 个父提交

< commit >^{ tree } commit 的树对象

HEAD~{< num >}

< tag >^{ commit } tag 的commit

< commit1 >..< commit2 > 从 commit1 开始到 commit2 为止的所有提交

git cherry-pick 会把commits 提交的改动作为一个新的提交,提交到当前分支

构造根提交:

  1. git commit-tree < tree object > 创建一个只有 树对象, 没有父提交的提交,也就是根提交。常常用于丢弃历史提交。
  2. git hash-object 直接产生 hash 码的方法,用文件内容产生提交。

git rebase

将 commit2 的提交,依次提交到 commit 上。commit2的提交以 commit1的最后一次提交为父提交。

git merge

刷新 工作区,暂存区

git checkout 一般只是改写 HEAD 文件的内容,但是添加 option ,可以使得 git checkout 不仅改变 HEAD, 而且改变 index, 以及 工作区。

git reset --hard 表示改变 HEAD, index 以及工作区。 --soft 表示仅仅改变 HEAD, 不改变 暂存区和工作区。

git checkout 把工作区filename文件的改动丢弃,也就是说用 暂存区中的 filename 文件替换工作区中的filename文件。

git checkout HEAD 丢弃 暂存区和工作区中的 filename 文件的改动。也就是说用HEADcommit 中的filename文件替换工作区和暂存区中的 filename 文件。

git clean 把所有版本库没有跟踪的 工作区的文件删除。

git remote:

  • 本地分支 当前版本库的分支

  • 远程分支 remotes 目录下的分支

  • 跟踪:建立分支时指定 --track 参数,可以跟踪分支。

  • 同名:两个分支名称相同。

git push: 合并本地分支和远程分支,并且把远程分支复制到上游版本库。这里面最重要的问题,如何合并。

合并的本地分支是那些,合并的远程分支是那些: 这个和 git 的配置文件(可以用 git config push.default 来设置)push.default 参数有关。常见的 push.default 参数值有:

  • simple, 合并的本地分支,是当前所在的分支。与之合并的远程分支是和 本地分支同名的远程分支,而且本地分支 track 远程分支。
  • upstream, 与同不同名 无关,所有本地分支合并与被本地分支 track 的远程分支。
  • nothing: 不推送任何东西
  • current: 推送当前分支到远程分支的同名分支。
  • matching: 推送本地版本库和远程版本库所有名字相同的分支。

git pull

git fetch

git

A 分支和 B 分支是否发生冲突,取决于: A1,A2, ... Am, B1, B2,...Bn B1,B2,... Bn, A1,A2,..., Am 的结果是否相同。 这样的话, 可以提交在某个分支中添加 提交来解决冲突(使得上面两个结果相同)。实际上也正是这样做的。

git cherry-pick: 我理解的git cherry-pick 是 把 提交 添加到分支上上的操作。 cherry-pick 可能会发生这样的 conflict, 比如 提交是 git rm data_sciene, 而当前 分支根本没有 datascience 文件,这就会报错。

验证修改的是内容还是只是相当于重复执行git指令。 cherry-pick 可以用来论证这个问题,在A分支中 写文件 a, 文件 a 的内容是 "a", 提交更改 git rm a。 在 B 分支中写个文件 a, 文件内容是 "b", 把 A 分支的 提交 cherry-pick 到 B 分支,如果顺利执行,说明 只是重复执行命令,如果不是说明 更改的是内容。我认为是后者。 果然如我所料,提交记住的是内容, 不是单纯的重复命令。

Git: 如果你做了错误的提交,最简单的办法是 git revert HEAD, 这样 git 会提交新的提交,新的提交会 undo 错误提交的更改。 但是,在本地版本库,我喜欢 git reset --hard HEAD^ 这样回滚到之前的提交,直接把错误的提交删掉。 现在 如果我已经把 错误的提交 push 到了远程版本库,有没有办法可以在远程版本库删掉 最开头的提交。 git push --force

你可以先把本地分支的提交删除,然后使用 git push 时,加上 --force 参数,强推,把 远程分支相应的提交也删除。

git push --delete

  • git push --delete HEAD 把远程的 HEAD 提交(最新提交)删除。
git reset HEAD^
git push orign +HEAD
⚠️ **GitHub.com Fallback** ⚠️