git 简要总结

基本概念

  • 工做区(working Directory)就是你在电脑里能看到的目录php

  • 版本库(repository) 工做区有一个隐藏目录.git,这个不算工做区,是版本库python

  • 暂存区 Git的版本库里存了不少东西,其中最重要的就是称为stage(或者叫index)的暂存区git

  • master 还有Git为咱们自动建立的第一个分支mastergithub

  • HEAD 指向master的一个指针叫HEADshell

咱们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit提交更改,实际上就是把暂存区的全部内容提交到当前分支。由于咱们建立Git版本库时,Git自动为咱们建立了惟一一个master分支,因此,如今,git commit就是往master分支上提交更改。能够简单理解为,须要提交的文件修改统统放到暂存区,而后,一次性提交暂存区的全部修改编程

安装git

mac上ubuntu

  1. 安装brewvim

    /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
  2. 安装gitapi

➜  ~ brew install git
#若出现下面的状况表示安装成功
➜  ~ git --version
git version 2.10.1

ubuntu上ruby

root@fan:~# sudo apt-get install git
sudo: 没法解析主机:fan
正在读取软件包列表... 完成
正在分析软件包的依赖关系树
正在读取状态信息... 完成
git 已是最新版 (1:2.7.4-0ubuntu1)。
升级了 0 个软件包,新安装了 0 个软件包,要卸载 0 个软件包,有 0 个软件包未被升级。

安装成功后还须要配置git

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
#配置别名
git config --global alias.st status #查看状态
git config --global alias.co checkout 
git config --global alias.ci commit #提交
git config --global alias.br branch #分支
git config --global alias.unstage 'reset HEAD --' 
git config --global alias.last 'log -1 HEAD'
git config --global alias.clog "log --color --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
git config --global alias.llog "log -graph --pretty=oneline --abbrev-commit"

还能够设置编辑器

git config --global core.editor vim

建立本地版本库

  • 建立裸仓库 git --base init

sh-3.2# pwd
/Applications/XAMPP/htdocs
sh-3.2# mkdir learngit
sh-3.2# cd learngit/
sh-3.2# #初始化目录为git能够管理的仓库
sh-3.2# git init
Initialized empty Git repository in /Applications/XAMPP/xamppfiles/htdocs/learngit/.git/

查看当前目录下会多了一个.git目录

sh-3.2# ls -ah
.    ..    .git

在这时最好先建好.gitignore 文件而后在commit,或者克隆远程仓库前,确保远程仓库.gitignore文件正确

远程仓库的管理和使用

克隆远程仓库

一次 Git 克隆会创建你本身的本地分支 master 和远程分支 origin/master,它们都指向 origin/master 分支的最后一次提交
克隆操做会默认使用的 master做为分支名 和 origin远程库名

git clone [url] 或者 git clone [url] + 要克隆到哪一个目录

$ git clone git://github.com/schacon/grit.git
$ git clone git://github.com/schacon/grit.git mygrit

添加远程仓库

  • git remote add [shortname] [url] 添加新的远程仓库

  • git remote 查看当前配置中每一个远程库的简短名称

    1. git remote -v显示克隆地址

  • git pull 命令自动抓取数据下来,而后将远端分支自动合并到本地仓库中当前分支

  • git fetch [shortname] 要抓取全部远程仓库有的,但本地仓库的远程分支没有的信息。若是是克隆了一个仓库,此命令会抓取从你上次克隆以来别人上传到此远程仓库中的全部更新。
    fetch 命令只是将远端的数据拉到本地仓库的远程分支,并不自动合并到当前工做分支,只有当你确实准备好了,才能手工合并

$ git fetch origin
remote: Counting objects: 20, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 15 (delta 5), reused 0 (delta 0)
Unpacking objects: 100% (15/15), done.
From git@github.com:schacon/simplegit
 * [new branch]      serverfix    -> origin/serverfix

在 fetch 操做下载好新的远程分支以后,你仍然没法在本地编辑该远程仓库中的分支。换句话说,在本例中,你不会有一个新的serverfix 分支,有的只是一个你没法移动的 origin/serverfix 指针
若是要把该内容合并到当前分支,能够运行 git merge origin/serverfix。若是想要一份本身的 serverfix 来开发,能够在远程分支的基础上分化出一个新的分支来:

$ git checkout -b serverfix origin/serverfix
Branch serverfix set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "serverfix"

这会切换到新建的 serverfix 本地分支,其内容同远程分支 origin/serverfix 一致,这样你就能够在里面继续开发了。

举例

root@fan:/home/wwwroot/git# git init
    初始化空的 Git 仓库于 /home/wwwroot/git/.git/
    root@fan:/home/wwwroot/git# git status
    位于分支 master
    
    初始提交
    
    无文件要提交(建立/拷贝文件并使用 "git add" 创建跟踪)
    root@fan:/home/wwwroot/git# git remote add demo git@git.coding.net:fan_code/ceshi2.git
    root@fan:/home/wwwroot/git# git remote
    demo
    root@fan:/home/wwwroot/git# git remote -v
    demo    git@git.coding.net:fan_code/ceshi2.git (fetch)
    demo    git@git.coding.net:fan_code/ceshi2.git (push)
    root@fan:/home/wwwroot/git# git fetch demo 
    remote: Counting objects: 7993, done.
    remote: Compressing objects: 100% (4985/4985), done.
    remote: Total 7993 (delta 2470), reused 7993 (delta 2470)
    接收对象中: 100% (7993/7993), 7.59 MiB | 337.00 KiB/s, 完成.
    处理 delta 中: 100% (2470/2470), 完成.
    来自 git.coding.net:fan_code/ceshi2
     * [新分支]          master     -> demo/master

如今,远程仓库[shortname]的主干分支(master)已经彻底能够在本地访问了,对应的名字是 demo/master,你能够将它合并到本身的某个分支,或者切换到这个分支,看看有些什么有趣的更新。

修改远程仓库地址

Git 仓库地址修改办法 git remote set-url origin [NEW_URL]

推送数据到远程仓库

  • git push [remote-name] [branch-name]

例如:把本地的 master 分支推送到origin 服务器上

$ git push origin master

把本地的 master 分支推送到 origin 上并更名为 test

$ git push origin master:test

查看远程仓库信息

  • git remote show [remote-name] 查看某个远程仓库的详细信息

举例

$ git remote show origin
* remote origin
  URL: git@github.com:defunkt/github.git
  Remote branch merged with 'git pull' while on branch issues
    issues
  Remote branch merged with 'git pull' while on branch master
    master
  New remote branches (next fetch will store in remotes/origin)
    caching
  Stale tracking branches (use 'git remote prune')
    libwalker
    walker2
  Tracked remote branches
    acl
    apiv2
    dashboard2
    issues
    master
    postgres
  Local branch pushed with 'git push'
    master:master

它告诉咱们,运行 git push 时缺省推送的分支是什么(译注:最后两行)。它还显示了有哪些远端分支尚未同步到本地(译注:第六行的caching 分支),哪些已同步到本地的远端分支在远端服务器上已被删除(译注:Stale tracking branches 下面的两个分支),以及运行git pull 时将自动合并哪些分支(译注:前四行中列出的 issues 和 master 分支)。

远程仓库的移除和重命名

  • git remote rename 原名 新名

  • git remote rm 远程仓库别名 碰到远端仓库服务器迁移,或者原来的克隆镜像再也不使用,又或者某个参与者再也不贡献代码,那么须要移除对应的远端仓库,能够运行

文件管理

将已被git跟踪的文件移除跟踪

另一种状况是,咱们想把文件从Git仓库中删除(亦即从暂存区域移除),但仍然但愿保留在当前工做目录中。换句话说,仅是从跟踪清单中删除。好比一些大型日志文件或者一堆.a 编译文件,不当心归入仓库后,要移除跟踪但不删除文件,以便稍后在 .gitignore 文件中补上,用 --cached 选项便可:

$ git rm --cached readme.txt

删除文件

后面能够列出文件或者目录的名字,也可使用 glob 模式。比方说:

$ git rm log/\*.log

注意到星号*以前的反斜杠,由于Git有它本身的文件模式扩展匹配方式,因此咱们不用shell来帮忙展开(译注:实际上不加反斜杠也能够运行,只不过按照shell扩展的话,仅仅删除指定目录下的文件而不会递归匹配。上面的例子原本就指定了目录,因此效果等同,但下面的例子就会用递归方式匹配,因此必须加反斜 杠。)。此命令删除全部log/ 目录下扩展名为 .log 的文件。相似的好比:

$ git rm \*~

会递归删除当前目录及其子目录中全部 ~ 结尾的文件。

移动文件

不像其余的VCS系统,Git并不跟踪文件移动操做。若是在Git中重命名了某个文件,仓库中存储的元数据并不会体现出这是一次更名操做。不过Git很是聪明,它会推断出究竟发生了什么,至于具体是如何作到的,咱们稍后再谈。

既然如此,当你看到 Git 的 mv 命令时必定会困惑不已。要在 Git 中对文件更名,能够这么作:

$ git mv file_from file_to

它会恰如预期般正常工做。实际上,即使此时查看状态信息,也会明白无误地看到关于重命名操做的说明:

$ git mv README.txt README
$ git status
# On branch master
# Your branch is ahead of 'origin/master' by 1 commit.
#
# Changes to be committed:
#   (use "git reset HEAD 
    
    ..." to unstage)
#
#       renamed:    README.txt -> README
#

其实,运行 git mv 就至关于运行了下面三条命令:

$ mv README.txt README
$ git rm README.txt
$ git add README

如此分开操做,Git也会意识到这是一次更名,因此无论何种方式都同样。固然,直接用 git mv 轻便得多,不过有时候用其余工具批处理更名的话,要记得在提交前删除老的文件名,再添加新的文件名。

文件对比

  • git diff
    比较工做区和暂存区文件差别

  • git diff --staged/--cached
    比较暂存区和版本库文件差别

  • git diff HEAD 能够查看工做区和版本库里面最新版本的区别

  • git diff HEAD -- 文件名 能够查看指定文件工做区和版本库里面最新版本的区别

    举例

    root@fan:/home/wwwroot/Demo# vim t2
    root@fan:/home/wwwroot/Demo# git diff
    diff --git a/t2 b/t2
    index 9bc7ad0..2672a75 100644
    --- a/t2
    +++ b/t2
    @@ -1 +1,2 @@
     t2
    +t2
    root@fan:/home/wwwroot/Demo# git add t2
    root@fan:/home/wwwroot/Demo# git diff 
    root@fan:/home/wwwroot/Demo# git diff --staged 
    diff --git a/t2 b/t2
    index 9bc7ad0..2672a75 100644
    --- a/t2
    +++ b/t2
    @@ -1 +1,2 @@
     t2
    +t2
    root@fan:/home/wwwroot/Demo# git commit -m '+t2'
    [master 8a74487] +t2
     1 file changed, 1 insertion(+)
    root@fan:/home/wwwroot/Demo# git status
    位于分支 master
    您的分支领先 'origin/master' 共 5 个提交。
      (使用 "git push" 来发布您的本地提交)
    无文件要提交,干净的工做区
    root@fan:/home/wwwroot/Demo# git diff
    root@fan:/home/wwwroot/Demo# git diff --staged

提交历史

查看

git log 有许多选项能够帮助你搜寻感兴趣的提交,接下来咱们介绍些最经常使用的。

咱们经常使用 -p 选项展开显示每次提交的内容差别,

  • -2 则仅显示最近的两次更新:

$ git log -p -2
  • --stat,仅显示简要的增改行数统计

$ git log --stat
  • --pretty 选项

    能够指定使用彻底不一样于默认格式的方式展现提交历史。好比用oneline将每一个提交放在一行显示,这在提交数很大时很是有用**
$ git log --pretty=oneline
edde8f5624c75017e81004b221d2a70e5ed31092 update README.md
75cc8c7ad7cf14f6eaded270c6b472b0b18accbd Initial commit
  • 还能够用oneline结合--graph选项

    显示ASCII图形表示的分支合并历史,形象地展现了每一个提交所在的分支及其分化衍合状况, `--abbrev-commit` 仅显示sha-1前几个字符,而非全部字符**
$ git log --graph --pretty=oneline --abbrev-commit
*   6be44b4 merge dev
|\  
| * d081be9 I am dev
* | c65bc40 I am master
|/  
* aaa7a54 初始化
  • format

    能够定制要显示的记录格式,这样的输出便于后期编程提取分析
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 11 months ago : changed the version number
085bb3b - Scott Chacon, 11 months ago : removed unnecessary test code
a11bef0 - Scott Chacon, 11 months ago : first commit

格式占位符说明

选项     说明
%H    提交对象(commit)的完整哈希字串
%h    提交对象的简短哈希字串
%T    树对象(tree)的完整哈希字串
%t    树对象的简短哈希字串
%P    父对象(parent)的完整哈希字串
%p    父对象的简短哈希字串
%an    做者(author)的名字
%ae    做者的电子邮件地址
%ad    做者修订日期(能够用 -date= 选项定制格式)
%ar    做者修订日期,按多久之前的方式显示
%cn    提交者(committer)的名字
%ce    提交者的电子邮件地址
%cd    提交日期
%cr    提交日期,按多久之前的方式显示
%s    提交说明
  • git log 支持的其余命令选项

选项 说明
-p 按补丁格式显示每一个更新之间的差别。
--stat 显示每次更新的文件修改统计信息。
--shortstat 只显示 --stat 中最后的行数修改添加移除统计。
--name-only 仅在提交信息后显示已修改的文件清单。
--name-status 显示新增、修改、删除的文件清单。
--abbrev-commit 仅显示 SHA-1 的前几个字符,而非全部的 40 个字符。
--relative-date 使用较短的相对时间显示(好比,“2 weeks ago”)。
--graph 显示 ASCII 图形表示的分支合并历史。
--pretty 使用其余格式显示历史提交信息。可用的选项包括 oneline,short,full,fuller 和 format(后跟指定格式)。
  • 过滤log输出

选项 说明

-(n)    仅显示最近的 n 条提交
--since, --after 仅显示指定时间以后的提交。
--until, --before 仅显示指定时间以前的提交。
--author 仅显示指定做者相关的提交。
--committer 仅显示指定提交者相关的提交。

例如

$ git log --pretty="%h - %s" --author=gitster --since="2008-10-01"  --before="2008-11-01" --no-merges -- t/

修改最后一次提交

有时候咱们提交完了才发现漏掉了几个文件没有加,或者提交信息写错了。想要撤消刚才的提交操做,可使用--amend选项从新提交:启动文本编辑器后,会看到上次提交时的说明,编辑它确认没问题后保存退出,就会使用新的提交说明覆盖刚才失误的提交。

$ git commit -m 'initial commit'
$ git add forgotten_file
$ git commit --amend

上面的三条命令最终只是产生一个提交,第二个提交命令修正了第一个的提交内容。

例如:本机mac举例

root@fan:/home/wwwroot/Demo# vim README.md 
root@fan:/home/wwwroot/Demo# vim test.md 
root@fan:/home/wwwroot/Demo# git log --pretty=oneline --abbrev-commit -2
097860c one
90a8fec phpstorm idea
root@fan:/home/wwwroot/Demo# git add README.md 
root@fan:/home/wwwroot/Demo# git commit -m 'two'
[master 490cf35] two
 1 file changed, 1 insertion(+)
root@fan:/home/wwwroot/Demo# git status
位于分支 master
您的分支领先 'origin/master' 共 2 个提交。
  (使用 "git push" 来发布您的本地提交)
还没有暂存以备提交的变动:
  (使用 "git add <文件>..." 更新要提交的内容)
  (使用 "git checkout -- <文件>..." 丢弃工做区的改动)
    修改:     test.md
修改还没有加入提交(使用 "git add" 和/或 "git commit -a")
root@fan:/home/wwwroot/Demo# git add test.md 
root@fan:/home/wwwroot/Demo# git log --pretty=oneline --abbrev-commit -2
490cf35 two
097860c one
root@fan:/home/wwwroot/Demo# git commit --amend 
[master 372f01e] ootwo
 Date: Tue Dec 6 20:13:35 2016 +0800
 2 files changed, 2 insertions(+)
root@fan:/home/wwwroot/Demo# git log --pretty=oneline --abbrev-commit -2
372f01e ootwo
097860c one

git 各类撤销操做

版本回退

说明

相似3628164...882e1e0的是commit_id(版本号),和SVN不同,Git的commit_id不是1,2,3……递增的数字,而是一个SHA1计算出来的一个很是大的数字,用十六进制表示,并且你看到的commit_id和个人确定不同,以你本身的为准。为何commit_id须要用这么一大串数字表示呢?由于Git是分布式的版本控制系统,后面咱们还要研究多人在同一个版本库里工做,若是你们都用1,2,3……做为版本号,那确定就冲突了。

每提交一个新版本,实际上Git就会把它们自动串成一条时间线。若是使用可视化工具查看Git历史,就能够更清楚地看到提交历史的时间线

root@fan:/home/wwwroot/Demo# git log --pretty=oneline
8a744873ac755647767abd149adef2e86ae53d71 +t2
97a15f36b57f6a0c588a058f654901ebeab6de31 +t1
ec30b4cb269ca10560b9abfe203fdd7a5abc7cfb 初始化
  • HEAD指向的版本就是当前版本,HEAD^指的是上一个版本,HEAD^^指的是上上个版本。所以,Git容许咱们在版本的历史之间穿梭,使用命令git reset --hard commit_id。commit id版本号不必写全,前几位就能够了,Git会自动去找

  • 穿梭前,用git log能够查看提交历史,以便肯定要回退到哪一个版本。要重返将来,用git reflog查看命令提交历史,以便肯定要回到将来的哪一个版本

    举例

    root@fan:/home/wwwroot/Demo# git log --pretty=oneline --abbrev-commit 
    8a74487 +t2
    97a15f3 +t1
    ec30b4c 初始化
    root@fan:/home/wwwroot/Demo# git reset --hard HEAD^
    HEAD 如今位于 97a15f3 +t1
    root@fan:/home/wwwroot/Demo# git log --pretty=oneline --abbrev-commit 
    97a15f3 +t1
    ec30b4c 初始化
    root@fan:/home/wwwroot/Demo# git reflog
    97a15f3 HEAD@{0}: reset: moving to HEAD^
    8a74487 HEAD@{1}: commit: +t2
    97a15f3 HEAD@{2}: commit: +t1
    ec30b4c HEAD@{3}: commit: 初始化
    root@fan:/home/wwwroot/Demo# git reset --hard 8a74487
    HEAD 如今位于 8a74487 +t2
    root@fan:/home/wwwroot/Demo# git log --pretty=oneline --abbrev-commit 
    8a74487 +t2
    97a15f3 +t1
    ec30b4c 初始化
    root@fan:/home/wwwroot/Demo# git reflog
    8a74487 HEAD@{0}: reset: moving to 8a74487
    97a15f3 HEAD@{1}: reset: moving to HEAD^
    8a74487 HEAD@{2}: commit: +t2
    97a15f3 HEAD@{3}: commit: +t1
    ec30b4c HEAD@{4}: commit: 初始化

撤销文件修改

假如如今工做区,暂存区某个文件为版本2,版本库为版本1,修改工做区文件后,工做区变为版本3,运行命令git reset HAED file ,暂存区变为版本1,跟版本库一致,而工做区的版本还为版本3

  • 场景1:使用git checkout — readme.txt丢弃工做区修改

    当你改乱了工做区某个文件的内容,想直接丢弃工做区的修改时,用命令git checkout -- file。命令git checkout — readme.txt

    把readme.txt文件在工做区的修改所有撤销,这里有两种状况:一种是readme.txt自修改后尚未被放到暂存区,如今,撤销修改就回到和版本库如出一辙的状态;

    一种是readme.txt已经添加到暂存区后,又做了修改,如今,撤销修改就回到添加到暂存区后的状态。

    总之,就是让这个文件回到最近一次git commitgit add时的状态。

  • 场景2:使用git reset HEAD file丢弃暂存区修改

    当你不但改乱了工做区某个文件的内容,还添加到了暂存区时,添加完以后又修改了工做区,想丢弃暂存区的修改,分两步,

    1. 第一步用命令git reset HEAD file

    用命令git reset HEAD file能够把暂存区的修改撤销掉(unstage),而工做区的文件没有变化

    就回到了场景1,

    1. 第二步按场景1操做。

  • 场景3:版本回退

    已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退,不过前提是没有推送到远程库。

标签管理

新建

  • git tag <name>用于新建一个标签,默认标签是打在最新提交的commit上,也能够指定一个commit id;

  • git tag -a <tagname> -m "blablabla..."能够指定标签信息;

  • git tag -s <tagname> -m "blablabla..."能够用PGP签名标签;

查看

  • git tag能够查看全部标签,git show <tagname> 查看标签所指向的提交

    例子

    root@fan:/home/wwwroot/git/demo# git status
    位于分支 master
    无文件要提交,干净的工做区
    root@fan:/home/wwwroot/git/demo# git reflog
    7aca999 HEAD@{0}: commit: c
    a8e8e16 HEAD@{1}: commit: b
    9cab6a8 HEAD@{2}: commit (initial): a
    root@fan:/home/wwwroot/git/demo# clear
    
    root@fan:/home/wwwroot/git/demo# git tag 'cc'
    root@fan:/home/wwwroot/git/demo# git tag
    cc
    root@fan:/home/wwwroot/git/demo# git reflog
    7aca999 HEAD@{0}: commit: c
    a8e8e16 HEAD@{1}: commit: b
    9cab6a8 HEAD@{2}: commit (initial): a
    root@fan:/home/wwwroot/git/demo# git show cc
    commit 7aca999821cd3384d634a7985782e8816d851d9b
    Author: fan <fan@qq.com>
    Date:   Wed Dec 7 21:08:35 2016 +0800
    
        c
    
    diff --git a/c b/c
    new file mode 100644
    index 0000000..f2ad6c7
    --- /dev/null
    +++ b/c
    @@ -0,0 +1 @@
    +c
    root@fan:/home/wwwroot/git/demo# git tag -a bb -m 'bbbbb' a8e8e16
    root@fan:/home/wwwroot/git/demo# git tag
    bb
    cc
    root@fan:/home/wwwroot/git/demo# git show bb
    tag bb
    Tagger: fan <fan@qq.com>
    Date:   Wed Dec 7 21:09:52 2016 +0800
    
    bbbbb
    
    commit a8e8e16567a8c9adf06fe2778ee647250425451d
    Author: fan <fan@qq.com>
    Date:   Wed Dec 7 21:07:53 2016 +0800
    
        b
    
    diff --git a/b b/b
    new file mode 100644
    index 0000000..6178079
    --- /dev/null
    +++ b/b
    @@ -0,0 +1 @@
    +b

推送标签到服务器

  • 推送单个标签git push origin <tagname>

  • 推送全部标签git push origin --tags

删除服务器标签

  1. 首先删除本地标签git tag -d [tagname]

  2. 删除服务器上标签git push origin :refs/tags/[tagname]

    例子

    root@fan:/home/wwwroot/git/Demo# git pull
    Already up-to-date.
    root@fan:/home/wwwroot/git/Demo# git push origin --tags 
    Total 0 (delta 0), reused 0 (delta 0)
    To git@git.coding.net:fan_code/Demo.git
     * [new tag]         1 -> 1
     * [new tag]         2 -> 2
    root@fan:/home/wwwroot/git/Demo# git tag -d 1
    已删除标签 '1'(曾为 90a8fec)
    root@fan:/home/wwwroot/git/Demo# git tag
    2
    root@fan:/home/wwwroot/git/Demo# git push origin :refs/tags/1
    To git@git.coding.net:fan_code/Demo.git
    - [deleted]         1

分支管理

工做场景

假设此时,你忽然接到一个电话说有个很严重的问题须要紧急修补,那么能够按照下面的方式处理:

  1. 返回到原先已经发布到生产服务器上的分支。

  2. 为此次紧急修补创建一个新分支,并在其中修复问题。

  3. 经过测试后,回到生产服务器所在的分支,将修补分支合并进来,而后再推送到生产服务器上。

  4. 切换到以前实现新需求的分支,继续工做。在切换回来以后,应该也把当前分支的bug修复

查看分支 git branch [name]

  • [name] 是添加分支

  • -d [name] 删除干净的分支(假如分支中包含还没有合并进来的工做成果,则为不干净的分支)

  • -D [name] 强制删除

  • -v 查看各个分支最后一个提交对象的信息

  • --merged 查看哪些分支已被并入当前分支(也就是说哪些分支是当前分支的直接上游,若是有分支内容与当前分支内容一致,也会显示)

  • --no-merged 查看哪些分支未被并入当前分支

切换分支 git checkout [name]

git checkout master

它把 HEAD 指针移回到 master 分支,并把工做目录中的文件换成了 master 分支所指向的快照内容

建立并切换分支 git checkout -b [name]

合并分支到当前工做分支 git merge [被合并的分支]

分支合并分为:直接祖先合并、非直接祖先合并(会进行三方合并)

  1. 直接祖先合并

    • 合并时出现了“Fast forward”的提示。因为当前 master 分支所在的提交对象是要并入的 hotfix 分支的直接上游,Git 只需把master 分支指针直接右移。换句话说,若是顺着一个分支走下去能够到达另外一个分支的话,那么 Git 在合并二者时,只会简单地把指针右移,由于这种单线的历史分支不存在任何须要解决的分歧,因此这种合并过程能够称为快进(Fast forward)。

  2. 非直接祖先合并(合并mster-c4和iss53->c5)

      1. 此次你的开发历史是从更早的地方开始分叉的。因为当前 master 分支所指向的提交对象(C4)并非 iss53 分支的直接祖先,Git 不得不进行一些额外处理。就此例而言,Git 会用两个分支的末端(C4 和 C5)以及它们的共同祖先(C2)进行一次简单的三方合并计算。此次,Git 没有简单地把分支指针右移,而是对三方合并后的结果从新作一个新的快照,并自动建立一个指向它的提交对象(C6)。这个提交对象比较特殊,它有两个祖先(C4 和 C5)。

删除分支 git branch -d [name]

推送全部分支到远程仓库origin git push origin --all

root@fan:/home/wwwroot/git/Demo# git push origin --all
对象计数中: 3, 完成.
压缩对象中: 100% (3/3), 完成.
写入对象中: 100% (3/3), 280 bytes | 0 bytes/s, 完成.
Total 3 (delta 2), reused 0 (delta 0)
To git@git.coding.net:fan_code/Demo.git
 * [new branch]      dev -> dev
 * [new branch]      dev2 -> dev2
 * [new branch]      test -> test

长期分支

因为 Git 使用简单的三方合并,因此就算在较长一段时间内,反复屡次把某个分支合并到另外一分支,也不是什么难事。也就是说,你能够同时拥有多个开放的分支,每一个分支用于完成特定的任务,随着开发的推动,你能够随时把某个特性分支的成果并到其余分支中。

特性分支

在任何规模的项目中均可以使用特性(Topic)分支。一个特性分支是指一个短时间的,用来实现单一特性或与其相关工做的分支。可能你在之前的版本控 制系统里从未作过相似这样的事情,由于一般建立与合并分支消耗太大。然而在 Git 中,一天以内创建、使用、合并再删除多个分支是常见的事。

远程分支

远程分支(remote branch)是对远程仓库中的分支的索引。它们是一些没法移动的本地分支;只有在 Git 进行网络交互时才会更新。
咱们用 (远程仓库名)/(分支名) 这样的形式表示远程分支
一次 Git 克隆会创建你本身的本地分支 master 和远程分支 origin/master,它们都指向 origin/master 分支的最后一次提交

跟踪远程分支

从远程分支 checkout 出来的本地分支,称为_跟踪分支(tracking branch)_。跟踪分支是一种和远程分支有直接联系的本地分支。在跟踪分支里输入git push,Git 会自行推断应该向哪一个服务器的哪一个分支推送数据。反过来,在这些分支里运行 git pull 会获取全部远程索引,并把它们的数据都合并到本地分支中来。

在克隆仓库时,Git 一般会自动建立一个名为 master 的分支来跟踪 origin/master。这正是git push 和 git pull 一开始就能正常工做的缘由。固然,你能够为所欲为地设定为其它跟踪分支,好比origin 上除了 master 以外的其它分支。刚才咱们已经看到了这样的一个例子:git checkout -b [分支名] [远程名]/[分支名]。若是你有 1.6.2 以上版本的 Git,还能够用--track 选项简化:

$ git checkout --track origin/serverfix
Branch serverfix set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "serverfix"

要为本地分支设定不一样于远程分支的名字,只需在前个版本的命令里换个名字:

$ git checkout -b sf origin/serverfix
Branch sf set up to track remote branch refs/remotes/origin/serverfix.
Switched to a new branch "sf"

如今你的本地分支 sf 会自动向 origin/serverfix 推送和抓取数据了。

删除远程分支

若是再也不须要某个远程分支了,好比搞定了某个特性并把它合并进了远程的 master 分支(或任何其余存放稳定代码的地方),能够用这个很是无厘头的语法来删除它:git push [远程名] :[分支名]。若是想在服务器上删除serverfix 分支,运行下面的命令:

$ git push origin :serverfix
To git@github.com:schacon/simplegit.git
 - [deleted]         serverfix

有种方便记忆这条命令的方法:记住咱们不久前见过的 git push [远程名] [本地分支]:[远程分支] 语法,若是省略 [本地分支],那就等因而在说“在这里提取空白而后把它变成[远程分支]”。

在服务器上部署 Git

开始架设 Git 服务器前,须要先把现有仓库导出为裸仓库 — 即一个不包含当前工做目录的仓库。克隆时用 --bare 选项便可。裸仓库的目录名通常以.git 结尾,像这样:

$ git clone --bare my_project my_project.git
Initialized empty Git repository in /opt/projects/my_project.git/

有了裸仓库的副本后,剩下的就是把它放到服务器上并设定相关协议。假设一个域名为 git.example.com 的服务器已经架设好,并能够经过 SSH 访问,咱们打算把全部 Git 仓库储存在/opt/git 目录下。只要把裸仓库复制过去:

$ scp -r my_project.git user@git.example.com:/opt/git

如今,全部对该服务器有 SSH 访问权限,并可读取 /opt/git 目录的用户均可以用下面的命令克隆该项目:

$ git clone user@git.example.com:/opt/git/my_project.git

若是某个 SSH 用户对 /opt/git/my_project.git 目录有写权限,那他就有推送权限。
因而可知,根据现有的 Git 仓库建立一个裸仓库,而后把它放上你和同事都有 SSH 访问权的服务器是多么容易。如今已经能够开始在同一项目上密切合做了。
这是架设一个少数人具备链接权的 Git 服务的所有 — 只要在服务器上加入能够用 SSH 登陆的账号,而后把裸仓库放在你们都有读写权限的地方。一切都准备停当,无需更多。

小型安装

若是设备较少或者你只想在小型开发团队里尝试 Git ,那么一切都很简单。架设 Git 服务最复杂的地方在于帐户管理。若是须要仓库对特定的用户可读,而给另外一部分用户读写权限,那么访问和许可的安排就比较困难。
SSH 链接

若是已经有了一个全部开发成员均可以用 SSH 访问的服务器,架设第一个服务器将变得异常简单,几乎什么都不用作(正如上节中介绍的那样)。若是须要对仓库进行更复杂的访问控制,只要使用服务器操做系统的本地文件访问许可机制就好了。

若是须要团队里的每一个人都对仓库有写权限,又不能给每一个人在服务器上创建帐户,那么提供 SSH 链接就是惟一的选择了。咱们假设用来共享仓库的服务器已经安装了 SSH 服务,并且你经过它访问服务器。

有好几个办法可让团队的每一个人都有访问权。
第一个办法是给每一个人创建一个帐户,直截了当但略过繁琐。反复运行 adduser 并给全部人设定临时密码可不是好玩的。

第二个办法是在主机上创建一个 git 帐户,让每一个须要写权限的人发送一个 SSH 公钥,而后将其加入 git 帐户的~/.ssh/authorized_keys 文件。这样一来,全部人都将经过 git 帐户访问主机。这丝绝不会影响提交的数据 — 访问主机用的身份不会影响提交对象的提交者信息。

另外一个办法是让 SSH 服务器经过某个 LDAP 服务,或者其余已经设定好的集中受权机制,来进行受权。只要每一个人都能得到主机的 shell 访问权,任何可用的 SSH 受权机制都能达到相同效果。

1. 生成 SSH 公钥

大多数 Git 服务器都会选择使用 SSH 公钥来进行受权。系统中的每一个用户都必须提供一个公钥用于受权,没有的话就要生成一个。生成公钥的过程在全部操做系统上都差很少。首先先确认一下是否已经有一个公钥了。SSH 公钥默认储存在帐户的主目录下的~/.ssh 目录。进去看看:

$ cd ~/.ssh
$ ls
authorized_keys2  id_dsa       known_hosts
config            id_dsa.pub

关键是看有没有用 something 和 something.pub 来命名的一对文件,这个 something 一般就是 id_dsa 或 id_rsa。有 .pub 后缀的文件就是公钥,另外一个文件则是密钥。假如没有这些文件,或者干脆连.ssh 目录都没有,能够用 ssh-keygen 来建立。该程序在 Linux/Mac 系统上由 SSH 包提供,而在 Windows 上则包含在 MSysGit 包里:

$ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/Users/schacon/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /Users/schacon/.ssh/id_rsa.
Your public key has been saved in /Users/schacon/.ssh/id_rsa.pub.
The key fingerprint is:
43:c5:5b:5f:b1:f1:50:43:ad:20:a6:92:6a:1f:9a:3a schacon@agadorlaptop.local

它先要求你确认保存公钥的位置(.ssh/id_rsa),而后它会让你重复一个密码两次,若是不想在使用公钥的时候输入密码,能够留空。

如今,全部作过这一步的用户都得把它们的公钥给你或者 Git 服务器的管理员(假设 SSH 服务被设定为使用公钥机制)。他们只须要复制 .pub 文件的内容而后发邮件给管理员。公钥的样子大体以下:

$ cat ~/.ssh/id_rsa.pub 
ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAklOUpkDHrfHY17SbrmTIpNLTGK9Tjom/BWDSU
GPl+nafzlHDTYW7hdI4yZ5ew18JH4JW9jbhUFrviQzM7xlELEVf4h9lFX5QVkbPppSwg0cda3
Pbv7kOdJ/MTyBlWXFCR+HAo3FXRitBqxiX1nKhXpHAZsMciLq8V6RjsNAQwdsdMFvSlVK/7XA
t3FaoJoAsncM1Q9x5+3V0Ww68/eIFmb1zuUFljQJKprrX88XypNDvjYNby6vw/Pb0rwert/En
mZ+AW4OZPnTPI89ZPmVMLuayrD2cE86Z/il8b+gw3r3+1nKatmIkjn2so1d01QraTlMqVSsbx
NrRFi9wrf+M7Q== schacon@agadorlaptop.local

关于在多个操做系统上设立相同 SSH 公钥的教程,能够查阅 GitHub 上有关 SSH 公钥的向导:http://github.com/guides/prov...

2. 架设服务器

如今咱们过一边服务器端架设 SSH 访问的流程。本例将使用 authorized_keys 方法来给用户受权。咱们还将假定使用相似 Ubuntu 这样的标准 Linux 发行版。首先,建立一个名为 ‘git’ 的用户,并为其建立一个.ssh 目录。

$ sudo adduser git
$ su git
$ cd
$ mkdir .ssh

接下来,把开发者的 SSH 公钥添加到这个用户的 authorized_keys 文件中。假设你经过电邮收到了几个公钥并存到了临时文件里。重复一下,公钥大体看起来是这个样子:

$ cat /tmp/id_rsa.john.pub
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCB007n/ww+ouN4gSLKssMxXnBOvf9LGt4L
ojG6rs6hPB09j9R/T17/x4lhJA0F3FR1rP6kYBRsWj2aThGw6HXLm9/5zytK6Ztg3RPKK+4k
Yjh6541NYsnEAZuXz0jTTyAUfrtU3Z5E003C4oxOj6H0rfIF1kKI9MAQLMdpGW1GYEIgS9Ez
Sdfd8AcCIicTDWbqLAcU4UpkaX8KyGlLwsNuuGztobF8m72ALC/nLF6JLtPofwFBlgc+myiv
O7TCUSBdLQlgMVOFq1I2uPWQOkOWQAHukEOmfjy2jctxSDBQ220ymjaNsHT4kgtZg2AYYgPq
dAv8JggJICUvax2T9va5 gsg-keypair

只要把它们逐个追加到 authorized_keys 文件尾部便可:

$ cat /tmp/id_rsa.john.pub >> ~/.ssh/authorized_keys
$ cat /tmp/id_rsa.josie.pub >> ~/.ssh/authorized_keys
$ cat /tmp/id_rsa.jessica.pub >> ~/.ssh/authorized_keys

如今能够用 --bare 选项运行 git init 来创建一个裸仓库,这会初始化一个不包含工做目录的仓库。

$ cd /opt/git
$ mkdir project.git
$ cd project.git
$ git --bare init

这时,Join,Josie 或者 Jessica 就能够把它加为远程仓库,推送一个分支,从而把第一个版本的项目文件上传到仓库里了。值得注意的是,每次添加一个新项目都须要经过 shell 登入主机并建立一个裸仓库目录。咱们不妨以gitserver 做为 git 用户及项目仓库所在的主机名。若是在网络内部运行该主机,并在 DNS 中设定 gitserver 指向该主机,那么如下这些命令都是可用的:

# 在 John 的电脑上
$ cd myproject
$ git init
$ git add .
$ git commit -m 'initial commit'
$ git remote add origin git@gitserver:/opt/git/project.git
$ git push origin master

这样,其余人的克隆和推送也同样变得很简单:

$ git clone git@gitserver:/opt/git/project.git
$ vim README
$ git commit -am 'fix for the README file'
$ git push origin master

用这个方法能够很快捷地为少数几个开发者架设一个可读写的 Git 服务。

做为一个额外的防范措施,你能够用 Git 自带的 git-shell 工具限制 git 用户的活动范围。只要把它设为git 用户登入的 shell,那么该用户就没法使用普通的 bash 或者 csh 什么的 shell 程序。编辑 /etc/passwd 文件:

$ sudo vim /etc/passwd

在文件末尾,你应该能找到相似这样的行:

git:x:1000:1000::/home/git:/bin/sh

bin/sh 改成 /usr/bin/git-shell (或者用 which git-shell 查看它的实际安装路径)。该行修改后的样子以下:

git:x:1000:1000::/home/git:/usr/bin/git-shell

如今 git 用户只能用 SSH 链接来推送和获取 Git 仓库,而不能直接使用主机 shell。尝试普通 SSH 登陆的话,会看到下面这样的拒绝信息:

$ ssh git@gitserver
fatal: What do you think I am? A shell?
Connection to gitserver closed.

Gitosis 能够设置谁能读或者写哪一个项目

把全部用户的公钥保存在 authorized_keys 文件的作法,只能凑和一阵子,当用户数量达到几百人的规模时,管理起来就会十分痛苦。每次改删用户都必须登陆服务器不去说,这种作法还缺乏必要的权限管理 — 每一个人都对全部项目拥有完整的读写权限。

幸亏咱们还能够选择应用普遍的 Gitosis 项目。简单地说,Gitosis 就是一套用来管理 authorized_keys 文件和实现简单链接限制的脚本。有趣的是,用来添加用户和设定权限的并不是经过网页程序,而只是管理一个特殊的 Git 仓库。你只须要在这个特殊仓库内作好相应的设定,而后推送到服务器上,Gitosis 就会随之改变运行策略,听起来就很酷,对吧?

Gitosis 的安装算不上傻瓜化,但也不算太难。用 Linux 服务器架设起来最简单 — 如下例子中,咱们使用装有 Ubuntu 8.10 系统的服务器。

Gitosis 的工做依赖于某些 Python 工具,因此首先要安装 Python 的 setuptools 包,在 Ubuntu 上称为 python-setuptools:

$ apt-get install python-setuptools

接下来,从 Gitosis 项目主页克隆并安装:

$ git clone git://eagain.net/gitosis.git
$ cd gitosis
$ sudo python setup.py install

这会安装几个供 Gitosis 使用的工具。默认 Gitosis 会把 /home/git 做为存储全部 Git 仓库的根目录,这没什么很差,不过咱们以前已经把项目仓库都放在/opt/git 里面了,因此为方便起见,咱们能够作一个符号链接,直接划转过去,而没必要从新配置:

$ ln -s /opt/git /home/git/repositories

Gitosis 将会帮咱们管理用户公钥,因此先把当前控制文件更名备份,以便稍后从新添加,准备好让 Gitosis 自动管理 authorized_keys 文件:

$ mv /home/git/.ssh/authorized_keys /home/git/.ssh/ak.bak

接下来,若是以前把 git 用户的登陆 shell 改成 git-shell 命令的话,先恢复 ‘git’ 用户的登陆 shell。改过以后,你们仍然没法经过该账号登陆(译注:由于authorized_keys 文件已经没有了。),不过不用担忧,这会交给 Gitosis 来实现。因此如今先打开 /etc/passwd 文件,把这行:

git:x:1000:1000::/home/git:/usr/bin/git-shell

改回:

git:x:1000:1000::/home/git:/bin/sh

好了,如今能够初始化 Gitosis 了。你能够用本身的公钥执行 gitosis-init 命令,要是公钥不在服务器上,先临时复制一份:

$ sudo -H -u git gitosis-init < /tmp/id_dsa.pub
Initialized empty Git repository in /opt/git/gitosis-admin.git/
Reinitialized existing Git repository in /opt/git/gitosis-admin.git/

这样该公钥的拥有者就能修改用于配置 Gitosis 的那个特殊 Git 仓库了。接下来,须要手工对该仓库中的 post-update 脚本加上可执行权限:

$ sudo chmod 755 /opt/git/gitosis-admin.git/hooks/post-update

基本上就算是好了。若是设定过程没出什么差错,如今能够试一下用初始化 Gitosis 的公钥的拥有者身份 SSH 登陆服务器,应该会看到相似下面这样:

$ ssh git@gitserver
PTY allocation request failed on channel 0
fatal: unrecognized command 'gitosis-serve schacon@quaternion'
  Connection to gitserver closed.

说明 Gitosis 认出了该用户的身份,但因为没有运行任何 Git 命令,因此它切断了链接。那么,如今运行一个实际的 Git 命令 — 克隆 Gitosis 的控制仓库:

# 在你本地计算机上
$ git clone git@gitserver:gitosis-admin.git

这会获得一个名为 gitosis-admin 的工做目录,主要由两部分组成:

$ cd gitosis-admin
$ find .
./gitosis.conf
./keydir
./keydir/scott.pub

gitosis.conf 文件是用来设置用户、仓库和权限的控制文件。keydir 目录则是保存全部具备访问权限用户公钥的地方— 每人一个。在keydir 里的文件名(好比上面的 scott.pub)应该跟你的不同 — Gitosis 会自动从使用 gitosis-init 脚本导入的公钥尾部的描述中获取该名字。

看一下 gitosis.conf 文件的内容,它应该只包含与刚刚克隆的 gitosis-admin 相关的信息:

$ cat gitosis.conf 
[gitosis]

[group gitosis-admin]
writable = gitosis-admin
members = scott

它显示用户 scott — 初始化 Gitosis 公钥的拥有者 — 是惟一能管理 gitosis-admin 项目的人。

如今咱们来添加一个新项目。为此咱们要创建一个名为 mobile 的新段落,在其中罗列手机开发团队的开发者,以及他们拥有写权限的项目。因为 ‘scott’ 是系统中的惟一用户,咱们把他设为惟一用户,并容许他读写名为iphone_project 的新项目:

[group mobile]
writable = iphone_project
members = scott

修改完以后,提交 gitosis-admin 里的改动,并推送到服务器使其生效:

$ git commit -am 'add iphone_project and mobile group'
[master]: created 8962da8: "changed name"
 1 files changed, 4 insertions(+), 0 deletions(-)
$ git push
Counting objects: 5, done.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 272 bytes, done.
Total 3 (delta 1), reused 0 (delta 0)
To git@gitserver:/opt/git/gitosis-admin.git
   fb27aec..8962da8  master -> master

在新工程 iphone_project 里首次推送数据到服务器前,得先设定该服务器地址为远程仓库。但你不用事先到服务器上手工建立该项目的裸仓库— Gitosis 会在第一次遇到推送时自动建立:

$ git remote add origin git@gitserver:iphone_project.git
$ git push origin master
Initialized empty Git repository in /opt/git/iphone_project.git/
Counting objects: 3, done.
Writing objects: 100% (3/3), 230 bytes, done.
Total 3 (delta 0), reused 0 (delta 0)
To git@gitserver:iphone_project.git
 * [new branch]      master -> master

请注意,这里不用指明完整路径(实际上,若是加上反而没用),只须要一个冒号加项目名字便可 — Gitosis 会自动帮你映射到实际位置。

要和朋友们在一个项目上协同工做,就得从新添加他们的公钥。不过此次不用在服务器上一个一个手工添加到 ~/.ssh/authorized_keys 文件末端,而只需管理keydir 目录中的公钥文件。文件的命名将决定在 gitosis.conf 中对用户的标识。如今咱们为 John,Josie 和 Jessica 添加公钥:

$ cp /tmp/id_rsa.john.pub keydir/john.pub
$ cp /tmp/id_rsa.josie.pub keydir/josie.pub
$ cp /tmp/id_rsa.jessica.pub keydir/jessica.pub

而后把他们都加进 ‘mobile’ 团队,让他们对 iphone_project 具备读写权限:

[group mobile]
writable = iphone_project
members = scott john josie jessica

若是你提交并推送这个修改,四个用户将同时具备该项目的读写权限。

Gitosis 也具备简单的访问控制功能。若是想让 John 只有读权限,能够这样作:

[group mobile]
writable = iphone_project
members = scott josie jessica

[group mobile_ro]
readonly = iphone_project
members = john

如今 John 能够克隆和获取更新,但 Gitosis 不会容许他向项目推送任何内容。像这样的组能够随意建立,多少不限,每一个均可以包含若干不一样的用户和项目。甚至还能够指定某个组为成员之一(在组名前加上@ 前缀),自动继承该组的成员:

[group mobile_committers]
members = scott josie jessica

[group mobile]
writable  = iphone_project
members   = @mobile_committers

[group mobile_2]
writable  = another_iphone_project
members   = @mobile_committers john

若是遇到意外问题,试试看把 loglevel=DEBUG 加到 [gitosis] 的段落(译注:把日志设置为调试级别,记录更详细的运行信息。)。若是一不当心搞错了配置,失去了推送权限,也能够手工修改服务器上的/home/git/.gitosis.conf 文件 — Gitosis 实际是从该文件读取信息的。它在获得推送数据时,会把新的 gitosis.conf 存到该路径上。因此若是你手工编辑该文件的话,它会一直保持到下次向 gitosis-admin 推送新版本的配置内容为止。

工做流程

提交规范

请将每次提交限定于完成一次逻辑功能。而且可能的话,适当地分解为屡次小更新,以便每次小型提交都更易于理解。请不要在周末穷追猛打一次性 解决五个问题,而最后拖到周一再提交。就算是这样也请尽量利用暂存区域,将以前的改动分解为每次修复一个问题,再分别提交和加注说明。若是针对两个问题 改动的是同一个文件,能够试试看git add --patch 的方式将部份内容置入暂存区域(咱们会在第六章再详细介绍)。不管是五次小提交仍是混杂在一块儿的大提交,最终分支末端的项目快照应该仍是同样的,但分解开 来以后,更便于其余开发者复阅。这么作也方便本身未来取消某个特定问题的修复。咱们将在第六章介绍一些重写提交历史,同暂存区域交互的技巧和工具,以便最 终获得一个干净有意义,且易于理解的提交历史

最后须要谨记的是提交说明的撰写。写得好可让你们协做起来更轻松。通常来讲,提交说明最好限制在一行之内,50 个字符如下,简明扼要地描述更新内容,空开一行后,再展开详细注解。Git 项目自己须要开发者撰写详尽注解,包括本次修订的因由,以及先后不一样实现之间的比较,咱们也该借鉴这种作法

例如

本次更新的简要描述(50 个字符之内)

若是必要,此处展开详尽阐述。段落宽度限定在 72 个字符之内。
某些状况下,第一行的简要描述将用做邮件标题,其他部分做为邮件正文。
其间的空行是必要的,以区分二者(固然没有正文另当别论)。
若是并在一块儿,rebase 这样的工具就可能会迷惑。

另起空行后,再进一步补充其余说明。

 - 可使用这样的条目列举式。

 - 通常以单个空格紧跟短划线或者星号做为每项条目的起始符。每一个条目间用一空行隔开。
   不过这里按本身项目的约定,能够略做变化。
  • 工做流程

    最简单的协做方式之一:先在本身的特性分支中工做一段时间,完成后合并到本身的 master 分支;而后下载合并 origin/master 上的更新(若是有的话),再推回远程服务器。
相关文章
相关标签/搜索