git简明使用手册

git作为时下最流行的代码管理工具,Git权威指南总结了十条喜欢Git的理由:

  • 异地协同工作;
  • 现场版本控制;
  • 重写提交说明;
  • 无尽的后悔药;
  • 更好用的提交列表;
  • 更好的差异比较;
  • 工作进度保存;
  • 作为SVN前端实现移动办公;
  • 无处不在的分页器;
  • 快。

其中:

  • git作为分布式代码管理工具,每个运行节点都保存有代码仓库的所有内容,都可以用来恢复服务器上的代码仓库;

  • git保存了所有代码仓库的操作记录,因此对本地代码仓库的操作都不需要进行任何备份,都可以无限回退。

  • 1. 概述

    • 1.1 git客户端安装
    • 1.2 git客户端配置
  • 2. git基础

    • 2.1 基本工作流程
    • 2.2 获取帮助信息
    • 2.3 合并比较结果阅读
    • 2.4 提交(commit)消息格式
  • 3. git仓库构成及访问路径

    • 3.1 远程仓库
      • 3.1.1 基本操作
      • 3.1.2 从远程仓库到本地仓库
      • 3.1.3 从本地仓库到远程仓库
    • 3.2 本地仓库
      • 3.2.1 查看本地仓库状态
      • 3.2.2 查看本地仓库日志(参见Git-工具-选择修订版本)
      • 3.2.3 查看本地仓库的git操作记录并无限回退
    • 3.3 分支
      • 3.3.1 查看分支信息
      • 3.3.2 从当前分支到其他分支
      • 3.3.3 从其他分支到当前分支
    • 3.4 工作区和暂存区
      • 3.4.1 查看工作区和暂存区内容
      • 3.4.2 从工作区到暂存区
      • 3.4.3 从暂存区到工作区
      • 3.4.4 从暂存区到本地仓库
      • 3.4.5 从本地仓库到暂存区即清除暂存区
      • 3.4.6 从本地仓库到工作区
      • 3.4.7 从工作区到本地仓库
      • 3.4.8 清除工作区
    • 3.5 临时缓冲区
      • 3.5.1 查看临时缓冲区
      • 3.5.2 从工作区和暂存区到临时缓冲区
      • 3.5.3 从临时缓冲区到工作区
  • 4. git进阶

    • 4.1 变基(参见Git权威指南-改变历史)
    • 4.2 二分法查找错误版本(参考Git权威指南-二分查找)
    • 4.3 压缩提交(参见Git-工具-重置揭密#压缩)
    • 4.4 拆分提交(参见Git-工具-重写历史#拆分提交)
    • 4.5 补丁操作(参见分布式-Git-向一个项目贡献#r_project_over_email和分布式 Git - 维护项目)

1. 概述

1.1 git客户端安装

  • 官方Windows客户端:主要使用Git Bash以命令行模式操作,但也支持GUI(gitk/git GUI),使用方法参见官方使用说明;
  • 官方Linux客户端:服务器已默认安装;
  • 更多图形工具,建议使用Source Tree

1.2 git客户端配置

远程仓库可以通过网页方式访问,但通常情况下仍然需要创建本地仓库:

  1. 创建本地 SSH key:

    • Windows下打开Git Bash,Linux下打开终端;
    • 执行ssh-keygen,所有提示均回车确认,生成私钥和公钥:

      <当前用户根目录>/.ssh/id_rsa
      <当前用户根目录>/.ssh/id_rsa.pub

    • 查看公钥文件内容并复制,注意不要复制命令本身

      cat <当前用户根目录>/.ssh/id_rsa.pub

  2. 添加远程仓库访问权限,不同的服务器会有不同的配置方法:

    • GitHub需要从右上角头像右侧的向下箭头进入settings->SSH and GPG keys来添加或者直接通过GitHub客户端自动添加;
    • gitolite需要将SSH公钥拷贝到gitolite-admin目录下的keydir目录中,并需要gitolite.conf已配置合适的访问权限。

    注意:

    • 本机SSH 私钥id_rsa不能删除。
    • 本机SSH key只需要创建一对,不需要为每个服务器都创建一对。
  3. 创建本地仓库并配置

    • 回到Git Bash/终端;
    • 执行

      git clone ssh://xxx.git

    • 执行本地配置(更多配置参见自定义-Git-配置-Git)

      git config --global user.name “姓名”
      git config --global user.email “邮箱”
      git config --global color.ui auto
      git config --global core.ignorecase false

      git config --global core.filemode false
      git config --global core.autocrlf input
      git config --global core.safecrlf true
      git config --global push.default simple
      git config --global rerere.enabled true
    • 配置完成后可显示本地配置信息

      git config -l --global

    注意

    • 自动补齐: Windows客户端默认支持命令补齐,服务器上Linux已经配置自动补齐,自行安装的Linux需要参考Git基础-技巧和窍门进行配置;
    • 命令别名:git允许为常用操作设置别名,以简化操作(参见Git-基础-Git-别名):

    git config --global alias.ci commit
    git config --global alias.unstage 'reset HEAD --'

2. git基础

2.1 基本工作流程

2.2 获取帮助信息

  • 联机帮助

    git help
    git help <命令名称>

  • 官方在线文档

  • Git权威指南在线版

2.3 合并比较结果阅读

git支持外部比较/合并工具(参见外部的合并与比较工具配置说明),但通常使用更为直接的命令行方式:

  • diff结果阅读
--- a/src/test.txt  :原始文件(以---开头) 
+++ b/src/test.txt  :目标文件(以+++开头) 
@@ -1,3 +1,3 @@     :当前差异块的比较对象为原始文件的第1行开始的3行与目标文件的地1行开始的3行
-orign              :只存在于原始文件(以-开头) 
+modified           :只存在于目标文件(以+开头)  
以空格开头           : 同时存在于原始文件和目标文件
  • merge结果阅读
<<<<<<<
当前分支代码
=======_
其他分支合并进来的代码
>>>>>>>

2.4 提交(commit)消息格式

git提交消息是日志回溯/代码审查/二分法问题查找的基础,建议参考thoughtbot规范:

50-character subject line

1. Why was this change necessary?

2. How does it address the problem?

3. Are there any side effects?

建议将模板保存在根目录下,使用如下命令配置为模板,这样在提交时就会自动显示:

git config --global commit.template <模板文件>

3. git仓库构成及访问路径

git简明使用手册_第1张图片
Paste_Image.png

3.1 远程仓库

远程仓库是服务器上的git仓库,支持如下常用操作(更多操作参见Git-基础-远程仓库的使用):

3.1.1 基本操作

  • 查看本地仓库远程仓库列表

    git remote -v

    如下所示:

    $ git remote -v
    origin  ssh://xxx.git (fetch)
    origin  ssh://xxx.git (push)
    

    注意:每个本地仓库可以从多个远程仓库获取代码,当前仅包含一个远程仓库origin。

  • 查看远程仓库概况

    git remote show <远程仓库名称>

    如下所示:

git简明使用手册_第2张图片
Paste_Image.png

该操作可用于查看远程仓库的地址,分支情况,与本地分支的差别等等。

3.1.2 从远程仓库到本地仓库

  • 创建新的本地仓库

    git clone <远程仓库路径> <可选的本地仓库目录名称>

  • 从远程仓库获取最新内容,包括新的分支以及原有分支上的改动

    git fetch

  • 从远程仓库获取最新内容,并合并到当前分支

    git pull

    注意:

    • 该操作相当于git fetch + git merge origin/<当前分支名称>,因此出现冲突时可以使用git merge --abort来终止;
    • 如果发生冲突,应当顺序执行如下操作:
      • 使用git merge --abort终止本次操作;
      • 使用git checkout -b temp创建并切换到1个临时分支;
      • 使用git branch -D <当前分支名称>删除当前分支;
      • 使用git checkout <当前分支名称>重新从远程分支创建本地分支;
      • 使用git branch -D temp删除临时分支。
    • !!!请勿使用--rebase选项,除非你知道你在干什么!!!

3.1.3 从本地仓库到远程仓库

  • 本地仓库更新到远程仓库

    git push

    注意

    • 若本地分支在远程仓库中没有对应的分支,则本操作会在远程仓库中创建同名分支并自动关联;
    • 若与远程仓库代码冲突且确认本地仓库没有问题,例如使用git rebase与master分支同步后,则可以使用git push --force来强制推送到服务器,从而使用本地仓库覆盖远程仓库;此时,远程仓库中的修改日志将会丢失

3.2 本地仓库

本地仓库是当前工作机器上的git仓库,支持如下常用操作:

3.2.1 查看本地仓库状态

  • 查看总体状态

    git status

git简明使用手册_第3张图片
Paste_Image.png

命令结果中注释如下:

  • 注1: 本地仓库当前分支名称;
  • 注2: 本地仓库当前分支与远程仓库同名分支之间的差异;
  • 注3: 推荐执行的操作;
  • 注4: 暂存区(stage)内容;
  • 注5: 工作区内容,对仓库中文件的修改;
  • 注6: 工作区内容,未加入到仓库中的文件。

3.2.2 查看本地仓库日志(参见Git-工具-选择修订版本)

  • 查看所有或某个文件的修改记录

    git log <可选文件路径>

  • 查看所有或某个文件的修改记录的概要(修改文件列别行数等)

    git log --stat <可选文件路径>

  • 图形化简略模式查看仓库日志

    git log --oneline --graph

    注意:在提交pull request之前,建议使用该命令确认需要合入主线的分支上没有重叠区域,例如下图中红圈所示的重叠线条,否则出现问题时难以定位错误提交:

git简明使用手册_第4张图片
Paste_Image.png
  • 查看本地分支与远程仓库master分支的差别,即本地分支对应的pull request包含的内容

    git log --oneline --left-right origin/master...<本地分支名称>

    对于未与远程仓库master分支同步即rebase的分支:

    $ git log --oneline --left-right origin/master...feature/KTOS-573-add-i2c-subsystem-2
    < deb713e Merge pull request #568 to master
    > be27660 XXXX
    ...
    < a674652 XXXX
    ...
    > c1a52d3 XXXX
    ...
    

    其中,<代表仅存在于远程分支上的提交,>代表仅存在于本地分支上的提交。而已经与远程仓库master分支同步即rebase的分支,则只包含>,即即仅存在于本地分支上的提交。

  • 查看某次提交中所有或某个文件的具体修改内容

    git show <提交ID> <可选文件路径>

  • 查看文件的历史版本

    git show <提交ID>:<文件路径>

  • 查看某个文件中所有或指定行的修改记录

    git blame <文件路径>
    git blame -L <起始行>,<结束行> <文件路径>
    git blame -L <起始行>,<+行数> <文件路径>

3.2.3 查看本地仓库的git操作记录并无限回退

  • 查看操作记录

    git reflog

git简明使用手册_第5张图片
Paste_Image.png
  • 回退到某次操作后的状态

    git reset HEAD@{序号}

    注意

    • 没有提到到仓库中的代码无法恢复;
    • 暂存区的代码会受影响,如需要保留可先提交到本地仓库进行备份。

3.3 分支

分支是指向提交的的可变指针(参见Git-分支-分支简介),每个git仓库都有一个默认创建的master分支和若干其他分支,支持如下常用操作:

3.3.1 查看分支信息

  • 查看本地分支信息

    git branch

    注意:当前分支名称之前会有*标志。

  • 查看本地分支详细信息

    git branch -v

Paste_Image.png
  • 查看包含分支标签的本地仓库日志

    git log --oneline --decorate

git简明使用手册_第6张图片
Paste_Image.png
  • 查看远程仓库分支信息

    git branch -r

git简明使用手册_第7张图片
Paste_Image.png
  • 查看所有分支(包含本地和远程仓库)信息

    git branch -a

Paste_Image.png

3.3.2 从当前分支到其他分支

  • 切换到本地仓库或远程仓库已有分支

    git checkout <分支名称>

  • 从当前分支创建一个新分支并切换到新分支

    git checkout -b <新分支名称>

  • 从某个提交创建一个新分支并切换到新分支(用于查看内容或者查找问题)

    git checkout <提交ID> -b <新分支名称>

  • 删除某个分支

    git branch -D <分支名称>

3.3.3 从其他分支到当前分支

  • 合并其他分支到当前分支,

    git merge <其他分支名称>

    注意

    • 该操作有可能造成提交交错,影响问题定位,因此不建议使用,除非你知道自己在干什么!!!
    • 如果合并过程中有冲突,需要顺序执行如下操作:
      • 编辑冲突文件,或删除不需要的文件;
      • 使用git add -u将修改添加到暂存区;
      • 使用git commit提交修改。
  • 终止当前合并操作

    git merge --abort

  • 将其他分支的某个提交合并到当前分支

    git cherry-pick <提交ID>

3.4 工作区和暂存区

工作区是工作目录的形象化称呼,实际上就是当前分支最新版本的本地副本;暂存区(stage)则是包含将要提交到本地仓库中的文件的索引列表(参见Git权威指南-git暂存区)。

3.4.1 查看工作区和暂存区内容

  • 查看工作区中文件的修改内容,即比较工作区与暂存区中的文件

    git diff <可选路径或文件名>

  • 查看暂存区中文件的修改内容,即比较暂存区与HEAD的文件

    git diff --cached <文件名>

  • 比较工作区与某个提交中的文件

    git diff <提交ID> <可选路径或文件名>

  • 比较暂存区与某个提交中的文件

    git diff --cached <提交ID> <可选路径或文件名>

  • 比较2个提交中的文件

    git diff <提交ID1> <提交ID2> <可选路径或文件名>
    git diff --name-only <提交ID1> <提交ID2> <可选路径或文件名>

    注意

    • 2个提交中必须包含对要比较的文件的修改,且提交ID1更旧;
    • --name-only用于只显示文件名。

3.4.2 从工作区到暂存区

  • 将工作区中的所有或某个文件放到暂存区

    git add <文件或目录路径>

  • 将工作区中所有对仓库中已有代码的修改放到暂存区

    git add -u

  • 以交互方式暂存文件

    git add -i

    注意

    • 该操作可以每一个被修改的文件和被修改的文件中的每一处修改都作出是否提交到暂存区的选择;
    • 详细操作参见Git-工具-交互式暂存。
  • 删除文件和目录

    git rm
    git rm -r

  • 移动文件和目录

    git mv

3.4.3 从暂存区到工作区

  • 将暂存区中对仓库中所有或某个文件的修改恢复到工作区

    git reset HEAD <可选的文件或目录路径>

3.4.4 从暂存区到本地仓库

  • 将暂存区中的内容提交到本地仓库(简单注释)

    git commit -m "注释信息"

  • 将暂存区中的内容提交到本地仓库(复杂注释,将会进入文本编辑界面,默认使用vi)

    git commit

  • 修改上次提交的注释信息

    git commit --amend -m "注释信息"

3.4.5 从本地仓库到暂存区即清除暂存区

  • 使用本地仓库中某个提交的代码覆盖暂存区并更新HEAD指针

    git reset <提交ID>

    注意,工作区的内容不受影响,但是暂存区中未提交到本地仓库中的修改会被覆盖。

3.4.6 从本地仓库到工作区

  • 使用本地仓库中的最新代码覆盖工作区中的内容,即撤销工作区内的所有或某个文件的修改

    git checkout .
    git checkout -- <文件或者目录名>

    注意:本操作实质上是用本地仓库中的数据覆盖工作区中的内容。

  • 使用本地仓库中某个提交的内容覆盖工作区中的某个文件或所有内容

    git checkout <提交ID> <可选的文件或者目录名>

  • 使用本地仓库中某个提交的内容覆盖工作区和暂存区并更新HEAD指针

    git reset --hard <提交ID>

3.4.7 从工作区到本地仓库

  • 直接将文件提交到本地仓库

    git commit -a -m "注释信息"

    注意,该操作不经过暂存区,务必慎用!!!

3.4.8 清除工作区

  • 清除工作区

    git clean -fd

3.5 临时缓冲区

临时缓冲区(stash)是保存临时修改内容的各个分支共享的全局缓冲区,支持如下常用操作(参见Git-工具-储藏与清理):

3.5.1 查看临时缓冲区

  • 显示临时缓冲区内保存的工作进度

    git stash list

    如下所示:

    $ git stash list
    stash@{0}: On bugfix/KTOS-499-pci-decouple: pci review
    

    其中,第1个:之前的部分是每个工作进度的标签,2个:之间的部分是保存该工作进度时所在的分支,第2个:之后的部分是该工作进度的描述信息。

  • 显示临时缓冲区某个工作进度的内容

    git stash show stash@{序号}

3.5.2 从工作区和暂存区到临时缓冲区

  • 将工作区和暂存区中对本地仓库中已有代码的修改备份到临时缓冲区

    git stash save "缓冲区描述"

  • 将工作区和暂存区中的所有修改(包括不在本地仓库中的文件)备份到临时缓冲区

    git stash save -u "缓冲区描述"

3.5.3 从临时缓冲区到工作区

  • 将临时缓冲区中对仓库中代码的修改弹出到工作区

    git stash pop stash@{序号}

  • 将临时缓冲区中对仓库中代码的修改应用到工作区(保留缓存区中的工作进度)

    git stash apply stash@{序号}

4. git进阶

4.1 变基(参见Git权威指南-改变历史)

  • 该操作的基本语法为:

    git rebase --onto <目的提交> <起始提交> <结束提交>

  • 变基操作会为切换到 <目的提交>,然后把<起始提交>和<结束提交>之间的提交逐条叠加到<目的提交>之后;如果--onto <目的提交>未指定,则使用<起始提交>;如果<结束提交>未指定,则使用当前分支;

  • 变基操作通常用于当前任务分支跟主线同步,例如git rebase master

  • 变基操作中出现问题时,需要根据对冲突的文件提示进行修改,完成后使用git add -u提交到暂存区,并使用git rebase --continue继续或git rebase --skip跳过当前提交继续同步;

  • 变基操作可以被git rebase --abort终止以恢复到操作前状态;

  • 变基操作结束以后,推送到服务器时,如果报错,需要使用git push --force强制推送。

  • 如果修改内容较多,且长时间未同步,可能会出现同一文件多次冲突,因此强烈建议打开Rerere功能:

    git config --global rerere.enabled true

    使能后,冲突解决方案会被记录,并在再次遇到时自动应用,不需要再吃手工编辑文件解决,只需要git add -u即可。

4.2 二分法查找错误版本(参考Git权威指南-二分查找)

该方法用于快速定位问题,但是需要如下条件作为前提才能高效工作:

  • 提交线性排序,不存在下图所示的重叠部分:
git简明使用手册_第8张图片
Paste_Image.png
  • 每个关键提交最好都能编译通过或运行。

该操作具体步骤如下(使用简单实例,具体使用时根据需要调整):

  • 查看当前日志

    $ git log --oneline**
    ebc659b second bad
    2fe7f29 first bad
    abfcfbc second good
    84ec8c3 first good
    
  • 启动查找

    $ git bisect start
    
  • 标志当前版本为坏版本

    $ git bisect bad
    
  • 标志某个好版本作为起点

    $  git bisect good 84ec8c3
    Bisecting: 0 revisions left to test after this (roughly 1 step)
    [2fe7f29987123abe3fa0cb3429c07b597f86594c] first bad
    

    此时会自动跳转到中间版本:

    $ git log --oneline
    2fe7f29 first bad
    abfcfbc second good
    84ec8c3 first good
    
  • 如果当前版本为坏版本,标志他

    $ git bisect bad
    Bisecting: 0 revisions left to test after this (roughly 0 steps)
    [abfcfbc361beb42551b4219d6d70ccb1fe3ac103] second good
    

    此时会自动跳转到中间版本:

    $ git log --oneline
    abfcfbc second good
    84ec8c3 first good
    
  • 如果当前版本为好版本,标志他

    $ git bisect good
    2fe7f29987123abe3fa0cb3429c07b597f86594c is the first bad commit
    commit 2fe7f29987123abe3fa0cb3429c07b597f86594c
    Author: Matt Zu
    Date:   Tue Dec 20 20:36:56 2016 +0800
        first bad
    :100644 100644 0cfbf08886fca9a91cb753ec8734c84fcbe52c9f c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 M      test.c
    

    找到第一个坏版本时,自动结束,不再跳转到中间版本:

    $ git log --oneline
    abfcfbc second good
    84ec8c3 first good
    
  • 切换到第一个坏版本

    $ git checkout bisect/bad
    Previous HEAD position was abfcfbc... second good
    HEAD is now at 2fe7f29... first bad
    

    日志如下:

    $ git log --oneline
    2fe7f29 first bad
    abfcfbc second good
    84ec8c3 first good
    

4.3 压缩提交(参见Git-工具-重置揭密#压缩)

每个pull request中应当包含尽可能少的提交,因此在推送到服务器之前,每个功能点或者修改点包含的所有提交都应当压缩成一个提交,并编译通过,最好能够通过基本测试。

该操作具体步骤如下(使用简单实例,具体使用时根据需要调整):

  • 查看当前日志

    $ git log --oneline
    f0fd7c9 commit msg 2
    335067c commit msg 1
    abfcfbc second good
    84ec8c3 first good
    
  • 查看文件修改记录

    $ git blame test.c
    abfcfbc3 (Matt Zu 2016-12-20 20:36:35 +0800 1) 2
    335067c5 (Matt Zu 2016-12-27 14:28:33 +0800 2) 3
    f0fd7c9b (Matt Zu 2016-12-27 14:28:48 +0800 3) 4
    
  • 将HEAD指针回退到需要合并的提交之前

    $ git reset --soft 335067c^
    

注意^用于回退到上一次提交,等价于~1;也可以叠加使用以回退到N次提交之前,等价于~N

  • 查看日志

    $ git log --oneline
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改内容

    $ git status
    On branch msg
    Changes to be committed:
      (use "git reset HEAD ..." to unstage)
    
            modified:   test.c
    $ git diff --cached
    diff --git a/test.c b/test.c
    index 0cfbf08..dcf37cd 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
     2
    +3
    +4
    
  • 再次提交代码以合并提交

    git commit -m "combine commit msg"
    
  • 查看日志

    $ git log --oneline
    a1fadaf combine commit msg
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改内容

    $ git log --oneline -p -1
    a1fadaf combine commit msg
    diff --git a/test.c b/test.c
    index 0cfbf08..dcf37cd 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
     2
    +3
    +4
    

4.4 拆分提交(参见Git-工具-重写历史#拆分提交)

该操作用于对不合理的提交压缩进行拆分,以方便cherry-pick和二分法查找等后续操作。

注意:该操作也可以用于调整提交的顺序,参见Git-工具-重写历史#重新排序提交。

该操作具体步骤如下(使用简单实例,具体使用时根据需要调整):

  • 查看日志

    $ git log --oneline
    0b22507 add aditional number
    abc373f update number and insert lines
    abfcfbc second good
    84ec8c3 first good
    

    假定abc373f为需要拆分的提交。

  • 查看修改内容

    $ git log --oneline -p -2
    0b22507 add aditional number
    diff --git a/test.c b/test.c
    index 2ff46c8..ab7998f 100644
    --- a/test.c
    +++ b/test.c
    @@ -1,3 +1,3 @@
    
    -3
    +3 4 5
    
    abc373f update number and insert lines
    diff --git a/test.c b/test.c
    index 0cfbf08..2ff46c8 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
    -2
    +
    +3
    +
    
  • 变基到需要拆分的提交(abc373f)之前

    $ git rebase -i abc373f^
    

    此时会进入vim界面,显示如下内容:

    pick abc373f update number and insert lines
    pick 0b22507 add aditional number
    
    # Rebase abfcfbc..0b22507 onto abfcfbc (2 commands)
    #
    # Commands:
    # p, pick = use commit
    # r, reword = use commit, but edit the commit message
    # e, edit = use commit, but stop for amending
    # s, squash = use commit, but meld into previous commit
    # f, fixup = like "squash", but discard this commit's log message
    # x, exec = run command (the rest of the line) using shell
    # d, drop = remove commit
    #
    # These lines can be re-ordered; they are executed from top to bottom.
    #
    # If you remove a line here THAT COMMIT WILL BE LOST.
    #
    # However, if you remove everything, the rebase will be aborted.
    #
    # Note that empty commits are commented out
    ~
    

    根据提示,将需要拆分的提交前面的pick修改为edit此处可以调整提交顺序):

    edit abc373f update number and insert lines
    pick 0b22507 add aditional number
    

    然后保存并退出,显示如下提示:

    $ git rebase -i abc373f^
    warning: Stopped at abc373f... update number and insert lines
    You can amend the commit now, with
    
      git commit --amend
    
    Once you are satisfied with your changes, run
    
      git rebase --continue
    
  • 查看日志

    $ git log --oneline
    abc373f update number and insert lines
    abfcfbc second good
    84ec8c3 first good
    
  • 回退HEAD指针到上一次提交

    $ git reset HEAD^
    Unstaged changes after reset:
    M       test.c
    
  • 查看修改内容

    $ git diff
    diff --git a/test.c b/test.c
    index 0cfbf08..2ff46c8 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
    -2
    +
    +3
    +
    
  • 将修改内容保存到临时缓冲区

    $ git stash save "msg split"
    Saved working directory and index state On (no branch): msg split
    HEAD is now at abfcfbc second good
    
  • 将修改内容应用到工作区并保留缓冲区中的进度

    $ git stash apply stash@{0}
    
  • 移除不需要的修改并提交(此处仅保留数字更新)

    $ git diff
    diff --git a/test.c b/test.c
    index 0cfbf08..00750ed 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1 @@
    -2
    +3
    $ git add -u
    $ git commit -m "update number"
    [detached HEAD c2b7f71] update number
     1 file changed, 1 insertion(+), 1 deletion(-)
    
  • 查看日志

    $ git log --oneline
    c2b7f71 update number
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改内容

    $ git log --oneline -p -1
    c2b7f71 update number
    diff --git a/test.c b/test.c
    index 0cfbf08..00750ed 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1 @@
    -2
    +3
    
  • 将修改内容弹出到工作区,修改冲突后再次提交

    $ git stash pop stash@{0}
    Auto-merging test.c
    CONFLICT (content): Merge conflict in test.c
    Recorded preimage for 'test.c'
    $ vim test.c
    $ git commit -m "insert lines"
    Recorded resolution for 'test.c'.
    [detached HEAD 13a6963] insert lines
     1 file changed, 2 insertions(+)
    
  • 查看日志

    $ git log --oneline
    13a6963 insert lines
    c2b7f71 update number
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改内容

    $ git log --oneline -p -2
    13a6963 insert lines
    diff --git a/test.c b/test.c
    index 00750ed..2ff46c8 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
    +
     3
    +
    c2b7f71 update number
    diff --git a/test.c b/test.c
    index 0cfbf08..00750ed 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1 @@
    -2
    +3
    
  • 继续变基

    $ git rebase --continue
    Successfully rebased and updated refs/heads/msg_split.
    
  • 查看日志

    $ git log --oneline
    dc4e8fa add aditional number
    13a6963 insert lines
    c2b7f71 update number
    abfcfbc second good
    84ec8c3 first good
    
  • 查看修改内容

    $ git log --oneline -p -3
    dc4e8fa add aditional number
    diff --git a/test.c b/test.c
    index 2ff46c8..ab7998f 100644
    --- a/test.c
    +++ b/test.c
    @@ -1,3 +1,3 @@
    
    -3
    +3 4 5
    
    13a6963 insert lines
    diff --git a/test.c b/test.c
    index 00750ed..2ff46c8 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1,3 @@
    +
     3
    +
    c2b7f71 update number
    diff --git a/test.c b/test.c
    index 0cfbf08..00750ed 100644
    --- a/test.c
    +++ b/test.c
    @@ -1 +1 @@
    -2
    +3
    

4.5 补丁操作(参见分布式-Git-向一个项目贡献#r_project_over_email和分布式 Git - 维护项目)

该操作用于创建和应用patch。

  1. 标准格式补丁创建

    每个标准格式补丁就是1个包含提交消息、修改文件概述和修改文件细节的mbox格式文件:

    $ cat 0001-test1.patch
    From 0d57e1ea1a27c54c7ec62cacfccb7d037923150a Mon Sep 17 00:00:00 2001
    From: matt 
    Date: Mon, 28 May 2018 16:29:57 +0800
    Subject: [PATCH 1/2] test1
    
    ---
     README | 2 +-
     1 file changed, 1 insertion(+), 1 deletion(-)
    
    !!!此处可以增加自定义信息以方便阅读,应用补丁时会被忽略。!!!
    
    diff --git a/README b/README
    index df1d5d6..3409f8c 100644
    --- a/README
    +++ b/README
    @@ -5,7 +5,7 @@
    
     Summary:
     ========
    -
    +1111111111111111111111111111111
     This directory contains the source code for U-Boot, a boot loader for
     Embedded boards based on PowerPC, ARM, MIPS and several other
     processors, which can be installed in a boot ROM and used to
    --
    2.10.1.windows.1
    

    操作命令如下所示:

    • git format-patch -M master

      为主线上不存在的每个提交创建一个标准格式补丁文件,同时查找重命名操作。注意,该操作需要切换到当前工作分支,并与主线同步后执行,即git checkout <工作分支>git rebase master之后。

    • git format-patch <起始提交ID或者标签>...<结束提交ID或者标签>

      为当前分支上起始提交ID或者标签与结束提交ID或者标签之间的每个提交创建一个标准格式补丁文件,不包括起始提交ID或者标签,但是包含结束提交ID或者标签。

      注意:

      • --cover-letter选项用于创建邮一个额外的mbox格式文件,包含所有提交的信息,而不只是某一个提交的信息。
        $ cat 0000-cover-letter.patch
        From 89d4c523ebf5bb6c700bcbf8e2c899c3f1d345fe Mon Sep 17 00:00:00 2001
        From: matt 
        Date: Tue, 29 May 2018 09:28:44 +0800
        Subject: [PATCH 0/2] *** SUBJECT HERE ***
        
        *** BLURB HERE ***
        
        matt (2):
          test1
          test2
        
         README | 2 +-
         1 file changed, 1 insertion(+), 1 deletion(-)
        
        --
        2.10.1.windows.1
        
      • 结束提交ID或者标签可以省略,默认为HEAD
    • git am <标准格式补丁文件>

      从标准格式补丁文件中读取补丁内容并应用到当前分支。注意,补丁文件应用冲突时,该操作会停下来,提示手工解决冲突,并在冲突解决后使用git am --resolved继续应用下一个补丁:

      $ vim README
      $ git add ticgit.gemspec
      $ git am --resolved
      Applying: test1
      

      当然,也可以跳过(git am --skip)或者终止(git am --abort)本次操作。

  2. diff格式补丁

    diff格式补丁使用diff命令创建,就是一个包含修改内容的文本文件,不包含提交消息和修改文件概述,但是可已经将多个提交的修改合并到一个文件中,方便阅读,但是应用补丁时只有补丁内容全部应用和完全不应用两种可能

    $ cat patch.txt
    diff --git a/README b/README
    index df1d5d6..3409f8c 100644
    --- a/README
    +++ b/README
    @@ -5,7 +5,7 @@
    
     Summary:
     ========
    -
    +1111111111111111111111111111111
     This directory contains the source code for U-Boot, a boot loader for
     Embedded boards based on PowerPC, ARM, MIPS and several other
     processors, which can be installed in a boot ROM and used to
    
    • git diff -c -p <起始提交ID或者标签>...<结束提交ID或者标签> > <补丁文件名称>

      将当前分支上起始提交ID或者标签与结束提交ID或者标签之间的所有修改创建一个diff格式补丁,不包括起始提交ID或者标签,但是包含结束提交ID或者标签。注意结束提交ID或者标签可以省略,默认为HEAD,例如:

      git diff -c -p HEAD^ > patch.txt

    • git apply <补丁文件名称>

      读取补丁内容并应用到当前分支。注意,本操作只修改当前分支文件,不会自动创建提交。

你可能感兴趣的:(git简明使用手册)