**# GIT 学习笔记
Git是什么
Git直接记录快照,并非差异比较
Git更像是把数据看作是对小型文件系统的一组快照。
每次提交更新,或在Git中保存项目状态时,主要是对当时的全部文件制作一个快照并保存这个快照的索引。
近乎所有操作都在本地执行
你在离线或者没有 VPN 时,几乎可以进行任何操作。
Git保证完整性
Git 中所有的数据在存储前都计算校验和,然后以校验和来引用。
Git 用以计算校验和的机制叫做 SHA-1 散列(hash,哈希)。
这是一个由 40 个十六进制字符(0-9 和 a-f)组成的字符串,基于 Git 中文件的内容或目录结构计算出来。
实际上,Git 数据库中保存的信息都是以文件内容的哈希值来索引,而不是文件名。
Git一般只添加数据
所有的Git 操作,几乎只往 Git 数据库中 添加 数据。
三种状态
已提交(committed)、已修改(modified) 和 已暂存(staged)。
三个阶段
工作区是对项目的某个版本独立提取出来的内容。
暂存区是一个文件,保存了下次将要提交的文件列表信息,一般在 Git 仓库目录中。
Git 仓库目录是 Git 用来保存项目的元数据和对象数据库的地方。
基本的工作流
- 在工作区中修改文件。
- 将你想要下次提交的更改选择性地暂存,这样只会将更改的部分添加到暂存区。
- 提交更新,找到暂存区的文件,将快照永久性存储到 Git 目录。
详见本文上述引用部分
初次运行Git前的配置
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。
- /etc/gitconfig 文件: 包含系统上每一个用户及他们仓库的通用配置。
如果在执行 git config 时带上**–system** 选项,那么它就会读写该文件中的配置变量。 - ~/.gitconfig 或 ~/.config/git/config 文件:只针对当前用户。 你可以传递 –global 选项让 Git读写此文件,这会对你系统上 所有 的仓库生效。
- 当前使用仓库的 Git 目录中的 config 文件(即 .git/config):针对该仓库。可以传递 –local 选项让 Git 强制读写此文件,虽然默认情况下用的就是它。
每一个级别会覆盖上一级别的配置,所以 .git/config 的配置变量会覆盖 /etc/gitconfig 中的配置变量。
查看所有的配置以及它们所在的文件命令:
git config --list --show-origin
配置用户信息
安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
当你想针对特定项目使用不同的用户名称与邮件地址时,可以在那个项目目录下运行没有 --global 选项的命令来配置。
配置文本编辑器
git config --global core.editor emacs
检查所有配置信息
git config --list
检查某一项配置
git config <key>
检查变量的原始值
git config --show-origin <variable>
获取帮助
git help <verb>
git <verb> --help
man git-<verb>
git <verb> -h # 只需要可用选项的快速参考
在已存在目录中初始化仓库
git init
git add *.cpp
git add LICENSE
git commit -m 'initial project version'
克隆现有的仓库
git clone [url]
git clone [url] [local_repository_name] # 自定义本地仓库的名字
检查当前文件状态
git status
git status -s # 状态间览,输出中有两栏,左栏指明了暂存区的状态,右栏指明了工作区的状态。
- 已跟踪的文件在上次提交后有没有被更改过
- 当前目录下没有出现任何处于未跟踪的新文件
- 显示当前分支,这个分支同远程服务器上对应的分支有没有偏离
添加内容到下一次提交中
git add README
- 跟踪新文件
- 把已跟踪的文件放到暂存区
- 用于合并时把有冲突的文件标记为已解决
忽略文件
创建一个名为 .gitignore 的文件,列出要忽略的文件的模式。
.gitignore的格式规范见p40
子目录下也可以有额外的 .gitignore 文件。子目录中的 .gitignore 文件中的规则只作用于它所在的目录中。
查看尚未暂存的文件更新了哪些部分
git diff
该命令比较的是工作目录中当前文件和暂存区域快照之间的差异。
查看已暂存的将要添加到下次提交里的内容
git diff --staged
git diff --cached
这条命令将比对已暂存文件与最后一次提交的文件差异
提交更新
默认的提交消息包含最后一次运行 git status 的输出,放在注释行里
git commit
git commit -v # 更详细的内容修改提示可以用 -v 选项查看
git commit -m # 将提交信息与命令放在同一行
git commit -a # Git 就会自动把所有已经跟踪过的文件暂存起来一并提交
git commit --amend # 将暂存区中的文件提交,或者只是修改提交信息,第二次提交将代替第一次提交的结果
移除文件
git rm # 简单地从工作目录中手工删除文件, 再运行git rm记录此次移除文件的操作, 如果要删除之前修改过或已经放到暂存区的文件,则必须使用强制删除选项 -f
git rm --cached # 把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。
移动文件
git mv file_from file_to
查看提交历史
git log
git log -p # 会显示每次提交所引入的差异
git log -<n> # 限制显示的日志条目数量
git log --stat # 显示每次提交的文件修改统计信息。
git log --pretty=oneline
git log --pretty=short
git log --pretty=full
git log --pretty=fuller
git log --pretty=format:"%h - %an, %ar : %s" # 常用的选项见p52
git log --graph # 添加了一些ASCII字符串来形象地展示分支、合并历史
git log --since=2.weeks # 列出最近两周的所有提交
git log --after
git log --until
git log --before
git log --author=pp # 显示指定作者的提交
git log --grep=new # 搜索提交说明中的关键字
git log --author=pp --author=bb # 输出匹配任意--author模式
git log --author=pp --author=bb --all-match # 输出匹配所有--author模式的提交
git log -S function_name # 找出添加或者删除了对某一个特定函数的引用的提交
git log -- path # 查看某些文件或者目录的历史提交
git log --no-merges # 避免显示的合并提交弄乱历史记录
git log 的常用选项见p53
取消暂存的文件
git reset HEAD <file>
撤消对文件的修改
对那个文件在本地的任何修改都会消失,add后不会消失
git checkout -- <file>
要读写远程仓库使用的 Git 保存的简写与其对应的 URL
git remote -v
添加远程仓库
git remote add <shortname> <url>
从远程仓库中抓取与拉取
git fetch <remote>
从最初克隆的服务器上抓取数据并自动尝试合并到当前所在的分支
git pull
推送到远程仓库
git push <remote> <branch>
查看某个远程仓库,还会列出了当你在特定的分支上执行 git push 会自动地推送到哪一个远程分支
git remote show <remote>
远程仓库的重命名与移除
git remote rename origin test
git remote remove origin
列出标签
git tag # 列出所有标签
git tag -l "v1.8.5*" # 按照通配符列出标签需要 -l 或 --list 选项
看到额外的标签信息
git show v1.4-lw
轻量标签(lightweight)与附注标签(annotated)
轻量标签很像一个不会改变的分支——它只是某个特定提交的引用。
附注标签是存储在 Git 数据库中的一个完整对象, 它们是可以被校验的,其中包含打标签者的名字、电子邮件地址、日期时间, 此外还有一个标签信息,并且可以使用 GNU Privacy Guard (GPG)签名并验证。
创建附注标签
git tag -a v1.4 -m "my version 1.4"
git tag -a v1.2 <校验和> # 给过去的提交打标签
创建轻量标签
git tag v1.4
共享标签
git push origin <tagname>
git push origin --tags # 会把所有不再远程仓库服务器上的标签全部传送到那里
删除标签
git tag -d <tagname> # 并不会从远程仓库中移除这个标签
git push <remote> :refs/tags/<tagname> # 将冒号前面的空值推送到远程标签名,从而高效删除
git push <remote> --delete <tagname> # 删除远程标签
检出标签
git checkout -b <new_branch> <tagnanme> # 在旧版本的基础上新建了一个分支
Git的分支模型
git的提交对象
三个 blob 对象(保存着文件快照)、一个 树 对象 (记录着目录结构和 blob 对象索引)以及一个 提交 对象(包含着指向前述树对象的指针和所有提交信息)
做些修改后再次提交,那么这次产生的提交对象会包含一个指向上次提交对象(父对象)的指针。
分支创建
git branch <branchname>
HEAD指针
HEAD是一个指针,指向当前所在的本地分支。
分支切换
git checkout <branchname>
git checkout -b <newbranchname> # 创建一个新分支后立即切换过去
查看分叉历史、提交历史、各个分支的指向以及项目的分支分叉情况
git tree --all
git log --oneline --all --graph
合并分支
git merge <branchname> # 检出到想合并入的分支,然后运行该命令
删除分支
git branch -d <branchname>
git branch -D <branchname> # 强制删除
合并冲突的解决办法
- 合并冲突后的任意时刻使用
git status
命令来查看那些因包含冲突而未合并状态的文件。 - 手动解决了所有文件的冲突之后,对每个文件使用
git add
命令来将其标记为冲突已解决。 - 可以再次运行git status来确认所有的合并冲突都已被解决。
- 确定之前有冲突的文件都已经暂存后,就可以输入
git commit
来完成合并提交。
查看所有分支
git branch
git branch -v # 查看每一个分支的最后一次提交
git branch --merged # 所有分支中已经合并的分支
git branch --no-merged # 所有分支中或尚未合并到当前分支的分支
git branch --no-merged <branchname> # 不必检出到<branchname>来查看其他分支的合并状态
远程分支
git ls-remote <remote> # 显式地获得远程引用地完整列表
git remote show <remote> # 获得远程分支的更多信息
远程跟踪分支是远程分支状态的引用
git clone -o booyah # 设置远程为booyah
推送
git push origin serverfix
git push origin refs/heads/serverfix:refs/heads/serverfix
git push origin serverfix:awesomebranch
git fetch的要点
当抓取到新的远程跟踪分支时,本地不会自动生成一份可编辑的副本(拷贝)
git fetch origin
git merge origin/serverfix
git checkout -b serverfix origin/serverfix # 给一个用于工作的本地分支,起点位于origin/serverfix
跟踪分支
git checkout -b <branch> <remote>/<branch>
git chekcout --track <remote>/<branch>
修改正在跟踪的上游分支
git branch -u origin/serverfix
查看设置的所有跟踪分支
git fetch --all
git branch -vv
删除远程分支
git push origin --delete serverfix
变基
git checkout experiment
git rebase master # rebase 命令将experiment上所作的修改都移至master分支上,修改的节点都放在master分支的后面
# 如果有冲突
git add <conflict_flie>
git checkout master
git merge experimemt
更有趣的变基
git rebase --onto master server client # 希望将client中的修改合并到主分支并发布,但暂时并不想合并server的修改
总的原则
只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作。
服务器端的Git
一个远程仓库通常只是一个裸仓库(bare repository),裸仓库就是你工程目录内的 .git子目录内容,不包含其他资料。
多种分布式工作流的细节
GitHub 托管服务以及深层次的工具
Git 的高级命令
Git 环境的自定义配置
对比 Git 和其它 VCSs
Git 隐晦而漂亮的实现细节
**