August 18, 2016

pro git 笔记

基础

名词

  • repository
  • track
  • stage
  • commit
  • pull
  • push

创建仓库

  1. 创建全新仓库

    $ git init
    $ git add (files)
    $ git commit -m (message)
    
  2. 克隆仓库

    $ git clone [url`
    

    克隆到的是远程几乎所有数据,而非仅为当前需要用到的数据

提交

被 git 管理的文件为已跟踪状态,其它为未跟踪。已跟踪的文件状态又可细分为:未修改、已修改和已暂存。四者之前的转换关系如下:

  • 未修改 文件可以从 git 中移除(remove),状态变为 未跟踪
  • 未跟踪 文件通过 add 命令加入 git 管理,状态变为 已暂存
  • 已修改 文件同样通过 add 命令加入暂存区,状态变为 已暂存
  • 已暂存 文件可以提交( commit )并创建快照 ,状态变为 未修改

通过 .gitignore 来设置文件匹配模式,自动忽略某些特定名称的文件(或目录)

常用的命令如下:

  • git status -s/--short 查看状态
  • git diff [--staged/--cached] 查看不同,加 cached 参数查看已暂存文件的不同
  • git add 加入未跟踪或已修改文件到暂存区
  • git commit [-a] [-m] [-v] 提交暂存修改
  • git rm --cached 剔除文件(从git管理),加 cached 参数保留原文件
  • git mv 重命名文件

历史

通过 git log 查看提交历史,有非常多的参数可选,常用的有

  • -p 显示具体修改内容
  • -2 仅显示最近两修改
  • --stat 显示统计信息(逐文件)
  • --sshortstat 显示简要统计信息
  • --pretty format,指定显示格式,例如 oneline, short, full, fuller, 具体的格式(类似printf)

author vs commitor 一次提交可能有不同的作者和提交者,前者是作出修改的人,后者是将修改提交到 git 的人

撤消

撤消操作可能会导致不可逆的数据丢失,谨慎操作!

三种常见的撤消操作如下

命令 说明
git commit --amend 重新提交,若快照无改动则只修改提交内容
git reset HEAD <file> 从暂存区域中移除,但不修改文件内容
git checckout -- <file> 检出文件内容,危险,对文件作的所有修改都被覆盖

远程仓库

相对本地仓库(当前目录)而言,指托管在网络中的版本库。同一个GIT仓库可以同时有多个远程仓库,常用命令如下

命令 说明
git remote -v 显示远程仓库列表
git remove add <snortname> <url> 添加一个新的远程仓库
git fetch [remote-name] 访问远程仓库,从中同步增量数据
git pull 拉取并合并(仅对于跟踪远程分支)
git push [remote-name] [branch-name] 推送本地分支到远端仓库,需要先拉取合并再推送
git remote show [remote-name] 显示远程仓库详情
git remote rm [remote-name] 删除远程仓库
git remote rename [from] [to] 重命名远程仓库

标签

指向某次提交,是之打上一个标记,常用于标记发行版本号。分为两种:

  1. lightweight tag
  2. annotated tag

前者是对某提交的引用,后者是一个完整的对象,包含独立的提交信息和备注

常用操作如下:

命令 说明
git tag -l 列出 tag
git tag v1.4-lw 添加轻量 tag
git tag -a v1.4 -m "<description>" [ref] 添加附注标签
git show [tagname] 显示 tag 详细信息
git push origin [tagname|--tags] 推送指定/全部 tag 到远程仓库
git checkout -b [branchname] [tagname] 按 tag 内容创建一个新的分支

别名

通过 git config --global alias.<alias> [fullcommand] 来设置别名,fullcommand 可以是 git 的命令也可以是外部命令(以 “!” 开头)

Branch(分支)

基础概念

GIT 对象分为三级:

  1. 文件快照,生成 blob 对象(原数据带 sha1 校验);
  2. 提交信息与提交的文件树,生成 tree 对象
  3. 与分支对应的 commit 对象,指向 tree 对象,并有 parent 表示上一次提交的路径

分支可以看作一个轻量指针,因此 git 中可以方便和简单的操纵多个分支。

分支操作的常用命令有:

  1. branch: 新建一个分支,即新建一个 commit 对象指向 HEAD 指针

    HEAD 是特殊的指针,指向当前所在的本地分支

  2. checkout: 切换分支( 修改 HEAD 指向 ),并恢复工作目录内容
  3. commit: 提交
  4. log: 常用参数有 –graph-all –decorate

分支与合并

分支使得可以随时从任何一处开启一个全新的开发过程。

两个分支形成分叉(diverged),分叉有两类关系

  1. 祖孙关系
  2. 公共的祖先关系

多个分支可能需要合并,以集成不同阶段的开发成果。使用 merge 命令进行自动合并,合并时:

  1. 祖孙关系:祖先提交指针右移,称作 fast-forward
  2. 公共祖先关系:进行三方合并(merge-in, merge-into, common-ancestor)

若两个分支对同一文件同一内容进行不一致的修改,无法自动合并。需要手工进行冲突排除

  1. 使用 git status 观察其中的 unmerged 文件
  2. 手工编辑解决冲突或使用 mergetool 进行操作
  3. add,commit 解决提交并记录解决方法

分支管理

git branch 有多种选项,其中参数 --merged--no-merged 可以限制分支选择方式 对于已经合并过的分支,可以放心删除之 git branch -d 而不损失历史内容

分支策略

分支有些习惯的用法,包含有:

  1. 流水线模式 提供不同级别的稳定性,master 保持稳定,将更新的开发置于 develop 分支

  2. 特性分支模式 将不同的需求开发分布于不同的短期分支中,方便进行上下文切换(context-switch),易于进行代码审查

远程分支

GIT 可以对多个远程仓库进行引用,使用 ls-remoteremote show 查看

对远程引用的只读操作在本地进行,其状态是最后一次通信时的记录,用 fetch 命令更新

远程引用包含了分支、标签等内容,远程分支表示为 remotes/(remote)/(branch)

创建跟踪分支

clone 远程仓库,生成 master 分支,与 origin/master 远程分支关联,称为跟踪分支(track)或上游分支(upstream)。也可以通过以下命令生成:

  • git checkout -b serverfix origin/serverfix
  • git checkout --track origin/serverfix

推送远程分支

本地分支通过 push 进行推送:

git push (remote) (branch)

上述 branch 完整应为 (local-branch):(remote-branch)

同步跟踪分支

使用 git pull,更明确的方法是先同步后合并

  1. git fetch
  2. git merge

删除远程分支

git push --delete serverfix

变基(rebase)

与 merge 进行三方合并效果一样,用于保证提交历史的整洁。rebase 后主分支只需要快进合并(fast-forward)即可

Rebase 原理是提取当前分支 C4 相对公共祖先提交 C2 的修改,在主分支 C3 进行重演。rebase 会遮掩提交历史,而且可能造成一些麻烦,merge 相对安全。

总的原则是 只对尚未推送或分享给别人的本地修改执行变基操作清理历史,从不对已推送至别处的提交执行变基操作 ,并在可能的情况下使用 git pull --rebase 来保证合并安全