概述
Git是一个用来做代码管理和版本控制的工具。
参考教程
《Git权威指南》,机械工业出版社,蒋鑫。
如有理解错误,欢迎指正。
总览
版本控制工具的发展
1.diff和patch。
2.CVS。
3.SVN。
4.Git。
Git初始化
git配置文件位置。
- 全局配置:/etc/gitconfig
- 个人配置:~/.gitconfig
- 具体Git库配置:/path/to/repo/.git/config
使用git config配置用户名和邮箱,--global表示当前用户。
git config --global user.name "Ruochen Xu"
git config --global user.email "ruochen.xu@aorise.com"
使用git config配置操作别名,可以让指令变短,--system表示所有用户。
git config --system alias.st status
注意:git config后的配置项都以a.b的形式表示。使用--unset删除配置。
使用git init创建空的本地git库,创建完成后,在库目录下有一个.git文件夹,里面存储了与本git库相关的所有信息。
cd /path/to/my/workspace
git init demo
生成一个新文件,并使用git add加入暂存区,然后使用git commit作一次的提交。
提交可以看做是一个确认的代码改动。
cd demo
echo "Hello." > readme.md
git add readme.md
git commit -m "Initialize.”
Git对象
Git中每个文件、每次提交、每个目录树等信息,都是以git对象的形式存储在库的.git/objects目录下的。每个git对象都有一个40位的SHA1哈希值,存储时前两位作为目录名,后38位作为文件名。
git cat-file -t <hash> # 查看git对象类型
git cat-file -p <hash> # 查看git对象内容
Git分支
Git进行第一次提交后,会自动生成第一个分支,也是默认分支,名称为master。
每次git commit提交都可以看做是一个点,相邻的提交之间有边相连,git每个提交都是增量的。每个提交都对应有一个文件目录树,代表的是从第一次提交开始到该提交结束,库中的文件。
每个分支就是一个指向某个提交的指针,代表着从第一次提交开始到该提交结束所有的文件变化历程。每个分支应当有一个独有的名字,HEAD表示当前正在操作的提交。
新的提交只能在某个分支上进行,即HEAD指针停留在某个分支指针上,而不能在任意提交上进行。
新分支可以从某个提交处产生,旧分支也可以与别的分支合并然后删除。所以所有的提交构成一张图。
Git的分支信息都存储在库的.git/refs/heads目录下,库的.git/HEAD文件存储HEAD指针的信息,库的.git/logs/refs/heads目录下记录了分支的变化历史。
Git提交的相对访问
^,父提交,^2,第二个父提交,例如HEAD^2。
~n,第n个祖先提交,例如HEAD~5。
^{tree},提交所对应的目录树,例如HEAD^{tree}。
:path/to/file,提交所对应的目录树中的文件,例如HEAD:path/to/file,不带分支名时指的是暂存区中的文件。
Git分支操作
分支移动。
git commit # 进行一次提交并将当前分支移动到新的提交
git reset <commit> # 将当前分支移动到指定提交
分支查看。
git branch -a
HEAD指针切换。
git checkout <commit>
从当前位置创建新分支。
git checkout -b <branch>
分支合并。
git merge <commit>
分支删除。
git branch -d <branch>
Git库类型
Git库主要分为三种类型。
1.bare,可读写的主库,一般放在远端服务器上,并设置成不能撤销写入的模式。不能在bare库本地直接对bare库进行操作。
2.mirror,可读不可写的bare库镜像,一般放在远端服务器上,也可以放在开发机上。可以在mirror库本地操作其与bare库进行同步。
3.local,可以任意操作的本地库,放在开发机上。可以与远端的bare、mirror库进行交互操作。
Git库的常规操作流程
1.使用git clone克隆远端bare库或者mirror库到本地,此时远端bare库默认使用origin这个名称。也可以使用git remote add将本地已初始化的库关联到远端bare库或者mirror库。
git clone git@github.com:hnxuruochen/test.git
git remote add origin git@github.com:hnxuruochen/test.git
注意:每个local库都可以有任意多个远端关联库,用不同的名称区分,origin是默认名称。
2.使用git pull将远端bare或者mirror库的指定分支的最新改动拉到本地当前分支。如果分支之间有冲突则需要进行冲突解决和分支合并。
git pull = git fetch + git merge
git pull origin <branch>
3.使用git push将本地库的当前分支的最新改动推到远端bare库的指定分支。如果分支之间有冲突则需要先通过git pull解决冲突并合并分之后,才能继续push。
git push origin <branch>
团队一般通过一个bare库,每人一个local库的方式进行合作开发。
Git文件区
Git库本地分为三个文件区。
1.工作区。存放本地文件的文件系统,对文件的改动都是在工作区完成的。
2.暂存区。用于记录和追踪文件状态的临时区,库的.git/index记录的就是暂存区的目录树。
3.版本库。存放确定文件改动的库。所有的提交、分支都是在版本库中的,bare、mirror库与local库的交互实际上是版本库的交互。
提交文件只能从工作区到暂存区,或者暂存区到版本库。还原文件只能从版本库到暂存区,或者暂存区到工作区。不能跨区操作。
文件区之间的操作
文件状态。
git status
文件比较。
git diff # 比较工作区与暂存区
git diff HEAD # 比较工作区与版本库中的当前提交
git diff --cached HEAD # 比较暂存区与版本库中的当前提交
文件提交。
git add <file> # 从工作区到暂存区
git commit # 从暂存区到版本库的新提交
文件还原。
git checkout -- <file> # 从暂存区到工作区
git reset HEAD # 从版本库中的当前提交到暂存区
git checkout HEAD <file> # 从版本库中的当前提交到暂存区再到工作区
文件删除。
git rm <file> # 删除工作区和暂存区中的文件
git rm --cached <file> # 只删除暂存区的文件
git clean # 删除工作区中未加入版本库的文件
Git存放处
Git还有一个特殊的文件区叫做stash,是用来临时存放当前工作区和暂存区的改动的。
每次存放相当于是作了一次不被实际应用的提交,然后记录在库的.git/refs/stash中,存放的变化存放在库的.git/logs/refs/stash中。
存储并撤销当前工作区和暂存区的改动。
git stash
恢复工作区和暂存区的改动。
git stash pop
查看所有存放的改动。
git stash list
Git里程碑
Git里程碑是人为对提交进行的命名。里程碑相关信息存储在库的,git/refs/tags目录下。
里程碑分类
1.轻量级里程碑,创建时使用-l参数。该里程碑本质上是一个提交,但是没有创建者信息。
2.带说明的里程碑,创建时使用-a或-m参数。该里程碑式一个tag对象。
3.带签名的里程碑,创建时使用参数-s或者-u。该里程碑也是一个tag对象,还添加了GnuPG签名。
里程碑操作
显示里程碑。
git tag
创建里程碑。
git tag <name>
删除里程碑。
git tag -d <name> # 删除本地
git push <remote> :<name> # 删除远程
推送里程碑。
git push <remote> <name>
Git子模块
Git库可以将其他git库作为子模块引入。
创建子模块。
git submodule add <repo_path> <submodule_path>
初始化子模块。
git submodule init
更新子模块。
git submodule update
查看子模块。
git submodule status
其他
文件忽略
可以通过编辑.gitignore文件来让git忽略一些仅在工作区中的文件,.gitignore文件可以放在任意目录下,对当前目录和子目录生效。
一些复杂的分支操作
git cherry-pick,将指定提交的增量改动应用到当前提交上。
git rebase,将指定的一段连续的增量提交应用到指定提交上。
git revert,使用一个新提交的方式撤销上一个提交的内容。
文件追溯
git blame指令可以追溯一个文件的改动历史信息。
网友评论