git 入门宝典

目录:

git 简介
    git 安装
    git的基本构成
    git的基本操作
        基本命令
        vi命令
        创建版本库
        添加文件
        提交文件
        查看状态
        查看提交日志
        查看更改对比
        版本回滚
        撤销操作
        删除操作
    远程仓库
        认识github
        克隆远程仓库
        推送与拉取
    分支
        分支的基本概念
        分支的常用命令
              创建分支
              切换分支
              创建并切换分支
              查看分支
              合并分支
              删除分支
        分支的注意事项
        分支冲突
        多人协作
        bug 分支
    标签
        标签的概念
        标签的常用命令
    自定义
        用户信息与加密key
        命令语法着色
        文件忽略
        自定义命令
        修改配置文件
        git常见问题


git 简介

git是由 Linus 开发的一种“分布式版本控制”软件,而在此之前,版本控制基本上都是“集中式版本控制”,如:CVS,SVN 等。
下图可以很好的帮助我们区分这两者:

"集中式版本控制系统"中,版本库是集中存放在中央服务器中的,开发人员在干活的时候,要先去访问中央服务器调取项目代码,然后才能修改,最后再提交到中央服务器中,供别人拉取使用。因此它有一个很大的缺点,那就是必须链接到中央服务器才能够正常工作。

相比较“集中式版本控制”,“分布式版本控制” 并没有真正意义上的中央服务器,而是开发者的每台电脑都可以作为一个中央节点来使用,因此工作时就无需链接主机,更不需要在只有有网络的环境下才能工作,而且分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。如果集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。

“分布式版本控制”也有中央节点的概念,这是因为在实际使用“分布式版本控制系统”的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。

git 安装

git的安装很简单,只需要下载git的程序安装包,安装好后即可,如果你是window系统,可以直接在自带的gitbash中执行相应的git命令,gitbash 默认便有相应的语法着色,如果你是mac系统,则在自己的终端中执行git命令,这里我推荐通过配置的方式设置git的语法作色,可以参考最后一章“自定义”。

Git Download>>>

git的基本构成

git的整体框架主要由两部分组成,它们分别是“工作区”和“版本库”。“工作区”就是我们本地的工作目录,而版本库则是我们通过 git init 命令创建的git仓库。
“版本库”用于监控文件的更改状态。它又有两个主要的部分构成,它们分别是:“暂存区”与“分支”,“暂存区”中保存的就是本地进行修改后等待提交的文件,而分支则是用于记录已经提交但是等待推送的文件。git默认的分支只有一个,那就是 master分支,但是git也支持多个分支,并且分支之间可以切换,可以合并。而 HEAD 便是分支的索引标识,类似于一个指针,用于确定当前活动的分支。

总的来说在git中发布一个版本,必须要经过以下几个步骤:

1. 在工作区中新建,编辑,保存文件。
2. 将编辑好的文件,添加至暂存区缓存
3. 确认无误后,将暂存区中的文件提交到分支中,等待推送。
4. 发布版本后,将本地仓库的文件推送至远程,以供别人拉取使用。

而在没有推送之前,这个文件的修改在“工作区”与“版本库”之间是可以相互重置撤销的。

git的基本操作

基本命令

下面是我们通过命令行工具来进行本地目录与文件操作的常用命令。

命令 功能
cd 进入到指定的目录。eg: cd d:/work/test
dir 列表化显示目录与文件。
ls 列表化显示目录与文件,但 win-cmd不支持
ls -a 列表化显示目录与文件包括隐藏文件,但 win-cmd不支持
mkdir 创建一个目录。eg:mkdir dirName
touch 创建一个空的文件。eg:touch fileName.txt
vi 使用内置vi编辑器来编辑文件。eg:vi fileName.txt
rm 删除文件。eg: rm fileName.txt
rm 删除目录。eg: rm -rf dirName
cat 查看文件内容。eg: cat fileName.txt
mv 移动文件或目录。eg: mv a.txt ../
find 搜索当前目录下的文件。eg: find *.txt
pwd 显示当前目录的路径。

vi命令

vi是Unix及Linux系统下标准的编辑器,由美国加州大学伯克利分校的Bill Joy所创立。
我们可以在支持 vi 编辑器的命令行工具中,直接调用vi来编辑文件。
vi 有两种状态是我们经常使用到的,分别是“命令模式”以及“编辑模式”。
vi默认的模式就是命令模式,通过在命令行中输入命令 a 便可以进入编辑模式,在编辑模式,按下 esc 键,再通过 shift+;(这里以window系统为例) 组合键,便又可返回命令模式。
下面是vi常用的命令:

命令 功能
a 进入编辑模式
q 退出vi编辑器
q! 强制退出vi编辑器
w 保存文件
wq 保存并退出
wq filename 保存文件退出并命名文件名称
yyp 复制光标所在的行再插入到下一行
dd 删除光标所在的行
u 返回上一次操作
set number 在编辑器中显示行号
set nonumber 在编辑器中隐藏行号
h 左移一个字符
l 右移一个字符
j 上移一行
k 下移一行

创建版本库

什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
git创建版本库非常简单,首先选择一个目录,然后执行以下命令即可。

Administrator@LS1412PC0008 MINGW64 /
$ cd d:/work/

Administrator@LS1412PC0008 MINGW64 /d/work
$ mkdir test

Administrator@LS1412PC0008 MINGW64 /d/work
$ cd test

Administrator@LS1412PC0008 MINGW64 /d/work/test
$ git init
Initialized empty Git repository in D:/work/test/.git/

瞬间Git就把仓库建好了,而且告诉你是一个空的仓库(empty Git repository),细心的读者可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。

如果你没有看到.git目录,那是因为这个目录默认是隐藏的,用 ls -a 命令就可以看见。

另外git仓库也不是全能的,它只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。

不幸的是,Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的,前面我们举的例子只是为了演示,如果要真正使用版本控制系统,就要以纯文本方式编写文件,并且强烈推荐文件的编码为UTF-8。

添加文件

添加文件是指将文件添加至版本库中的暂存区(stage),而暂存区中存放的内容,便是等待提交的内容。

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ touch name.txt

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ vi name.txt

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ git add name.txt

如果想一次性的将所有文件都添加至暂存区,可以用以下命令:

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
git add .

提交文件

如果暂存区中的文件确认无误的话,便可可使用以下命令将内容提交至分支中:

[email protected] MINGW64 /d/work/test (master)
$ git commit name.txt -m ‘commit name.txt‘
[master (root-commit) 0c2dc57] commit name.txt
1 file changed, 1 insertion(+)
create mode 100644 name.txt

其中 -m 是本次提交的注释内容,这个必须填写

如果你想将暂存区中的所有内容都提交到分支中,可以这么写

[email protected] MINGW64 /d/work/test (master)
$ git commit -m ‘commit all stage‘
[master d27ea06] commit all stage
1 file changed, 1 insertion(+), 1 deletion(-)

除此之外,你还可以将 add 与 commit 结合在一起使用

[email protected] MINGW64 /d/work/test (master)
$ git commit -a -m ‘add & commit‘
[master b602d26] add & commit
1 file changed, 1 insertion(+), 1 deletion(-)

查看状态

git status命令可以列出当前目录所有还没有被git管理的文件或者是被git管理且被修改但还未提交(commit)的文件。

[email protected] MINGW64 /d/work/test (master)
$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   name.txt

如果想看简明扼要一点的状态信息,可以加一个 -s 参数

[email protected] MINGW64 /d/work/test (master)
$ git status -s
M  name.txt

查看提交日志

在提交了若干版本之后,想回顾下提交历史,可以使用 git log 命令查看。

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ git log
commit b602d2600c2a4f84d427ff2a414a90384e77dfed
Author: guotaoShen <shenguotao@iwgame.com>
Date:   Thu Mar 30 11:00:19 2017 +0800

    add & commit

commit d27ea06b28a91095921ac55b2fb3c1f078e10a9b
Author: guotaoShen <shenguotao@iwgame.com>
Date:   Thu Mar 30 10:58:56 2017 +0800

    commit all stage

commit 0c2dc5716fc3b1ba0b8690a91e5dcad5d2b1dd24
Author: guotaoShen <shenguotao@iwgame.com>
Date:   Thu Mar 30 10:56:30 2017 +0800

    commit name.txt

在通过 git log 命令 打印的信息中,我们可以看到,git会按照提交时间去排序历史记录,最后一次提交排在最前面,除此之外,你还可以看到关于提交的一些标识,作者,时间,以及提交的说明等信息。

git log命令提供了很多可供自定义提交日志输出的格式,这里,我就选择几个最常用到的

一行显示提交历史记录
通过使用git log命令我们知道,打印出来的提交信息会占据多行,一旦提交次数变多到时候,这必将影响我们浏览。

[email protected] MINGW64 /d/work/test (master)
$ git log --pretty=oneline

b602d2600c2a4f84d427ff2a414a90384e77dfed add & commit
d27ea06b28a91095921ac55b2fb3c1f078e10a9b commit all stage
0c2dc5716fc3b1ba0b8690a91e5dcad5d2b1dd24 commit name.txt

显示提交文件的更改信息

[email protected] MINGW64 /d/work/test (master)
$ git log --pretty=oneline --stat

b602d2600c2a4f84d427ff2a414a90384e77dfed add & commit
 name.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

d27ea06b28a91095921ac55b2fb3c1f078e10a9b commit all stage
 name.txt | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

0c2dc5716fc3b1ba0b8690a91e5dcad5d2b1dd24 commit name.txt
 name.txt | 1 +
 1 file changed, 1 insertion(+)

显示提交文件的更改信息与更改内容

[email protected] MINGW64 /d/work/test (master)
$ git log --pretty=oneline -p -2

b602d2600c2a4f84d427ff2a414a90384e77dfed add & commit
diff --git a/name.txt b/name.txt
index 7e94c2b..9e0c614 100644
--- a/name.txt
+++ b/name.txt
@@ -1 +1 @@
-my name is shentao - 123
+my name is shentao - 1234

d27ea06b28a91095921ac55b2fb3c1f078e10a9b commit all stage
diff --git a/name.txt b/name.txt
index d137a88..7e94c2b 100644
--- a/name.txt
+++ b/name.txt
@@ -1 +1 @@
-my name is shentao - 12
+my name is shentao - 123

其中 -2 可以指定只显示前两条的提交信息,这个参数很实用,比如:

[email protected] MINGW64 /d/work/test (master)
$ git log --pretty=oneline -1
b602d2600c2a4f84d427ff2a414a90384e77dfed add & commit

查看更改对比

如果我们想比较一个文件在工作区与暂存区的更改状态,我们可以使用 git diff 命令。

[email protected] MINGW64 /d/work/test (master)
$ git diff name.txt

diff --git a/name.txt b/name.txt
index 465f661..d48e0e5 100644
--- a/name.txt
+++ b/name.txt
@@ -1,3 +1,4 @@
 my name is shentao - 12345
 new add line
 new add line 2
+new add line 3

如果想查看该文件在暂存区与分支中的更改对比,可以通过附加 --cached 实现

[email protected] MINGW64 /d/work/test (master)
$ git diff --cached
diff --git a/name.txt b/name.txt
index 8535cbf..465f661 100644
--- a/name.txt
+++ b/name.txt
@@ -1,2 +1,3 @@
 my name is shentao - 12345
 new add line
+new add line 2

若是想直接查看工作区与分支的对比状态,则可以附加 HEAD 参数。

[email protected] MINGW64 /d/work/test (master)
$ git diff HEAD
diff --git a/name.txt b/name.txt
index 8535cbf..d48e0e5 100644
--- a/name.txt
+++ b/name.txt
@@ -1,2 +1,4 @@
 my name is shentao - 12345
 new add line
+new add line 2
+new add line 3

版本回滚

通过 git reset 命令我们可以重置分支中最新的提交。
首先,我们先通过 git log --pertty=oneline 来查看提交的历史记录。

[email protected] MINGW64 /d/work/test (master)
$ git log --pretty=oneline
b602d2600c2a4f84d427ff2a414a90384e77dfed commit1
d27ea06b28a91095921ac55b2fb3c1f078e10a9b commit2
0c2dc5716fc3b1ba0b8690a91e5dcad5d2b1dd24 commit3

其中像 b602d2600c2a4f84d427ff2a414a90384e77dfed 的这样一串字母与数字的混合,就是该提交的索引,一般我们取前6位 b602d2,便可以供我们使用了。
拿到提交索引,我们便可以告诉git重置到那个提交版本。

[email protected] MINGW64 /d/work/test (master)
$ git reset --hard d27ea0
HEAD is now at d27ea0  commit2

此时我们便将分支中保存的最新提交 commit1 重置为了 commit2了。此时如果再使用 git log 去查看提交历史记录,便会惊讶的发现,commit1版本已经看不到了,但是如果你现在又要重新返回到 commit1版怎么办呢?
不要担心,虽然 git log 无法查看之前的版本,但是通过 git reflog 命令还是可以看到的提交的命令记录。

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ git reflog
b602d26 [email protected]{26}: commit: commit1
d27ea06 [email protected]{27}: commit: commit2
0c2dc57 [email protected]{28}: commit: commit3

在常规的使用时,git的版本重置还有一种简写方式。
git reset --hard HEAD ^ //返回到当前版本下一个版本

撤销操作

这里说的撤销操作,是指将暂存区的内容或者是提交后的内容撤销到工作区的操作。
首先我们准备一下要撤销的环境,这里我以 name.txt 为例,我会让该文件在不同的区域其内容不同。
在工作区:

add line to working

在暂存区:

add line to working
add line to staged

提交后再分支中:

add line to working
add line to staged
add line to staged

现在我们开始我们的撤销操作

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ cat name.txt
add line to working

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ git checkout name.txt

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ cat name.txt
add line to working
add line to staged

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ git checkout HEAD name.txt

Administrator@LS1412PC0008 MINGW64 /d/work/test (master)
$ cat name.txt
add line to working
add line to staged
add line to branch

删除操作

在gitbash中,我们可以通过 rm 命令来删除文件以及目录。

rm name.txt //删除文件
rm -rf .git //删除本地版本库目录

相同的git也自带了删除命令,使用者可以选择是否将工作区与暂存区的文件同时删除,还是保留工作区只删除暂存区。

git rm name.txt

同时删除工作区与暂存区

git rm --cached name.txt

删除暂存区,但保留工作区。

远程仓库

所谓的远程仓库,就是git的中央节点,也就是远程服务器上的git版本库,与我们本地并没有什么区别,纯粹为了7x24小时开机并交换大家的修改。
git的远程仓库或者是中央节点,既可以我们自己搭建一个内部的git服务器,也可以使用目前网上流行的github远程项目托管平台。

认识github

github 是一个面向开源及私有软件项目的托管平台,因为只支持 Git 作为唯一的版本库格式进行托管,故名github。
github 不仅仅单纯托管git版本库,还提供了跨平台的web操作界面,因此深受很多开发者喜爱。
github 上的代码项目都是公开的开源的,如果你想私有不公开你的项目代码,那么就需要缴纳一定的金额才能开通私有功能。
github的官网地址是:https://github.com/,想使用github的具体功能,你需要有一个账号。

克隆远程仓库

我们既可以将远程的版本库直接克隆到本地,也可以先创建本地的git版本库,然后再与远程的git仓库进行关联,具体使用哪一种,就看你个人的选择。通常来说,直接克隆的方式是最简单的,但是你不能确认在你开发之前,远程的git仓库就已经建好供你使用了。

需要说明的是,以下示例中的远程版本库都是以github上的远程仓库为例。

直接克隆远程版本库

Administrator@LS1412PC0008 MINGW64 /d/work
$ git clone https://github.com/shenguotao2015/fdasfdsafsaf.git

这种方式会将远程版本库克隆一个副本到本地,并且可以自动将本地版本库与远程版本库自动关联。

关联远程版本库

Administrator@LS1412PC0008 MINGW64 /d/work
$ mkdir test

Administrator@LS1412PC0008 MINGW64 /d/work
$ git init
Initialized empty Git repository in D:/work/.git/

Administrator@LS1412PC0008 MINGW64 /d/work (master)
$ git remote add origin https://github.com/shenguotao2015/test.git

这种方式先在本地创建一个git仓库,然后再通过 git remote 命令与远程版本库进行关联。
但如果我们关联的远程版本库有误的话,就需要先删除remote的origin再从新设定remote的origin

git rm remote origin
git remote add origin URL

推送与拉取

指定分支推送并关联远程库

$ git push -u origin master
Username for ‘https://github.com‘: shenguotao2015
Counting objects: 3, done.
Writing objects: 100% (3/3), 209 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
Branch master set up to track remote branch master from origin.
To https://github.com/shenguotao2015/fdasfdsafsaf.git
 * [new branch]      master -> master

默认分支推送

 git push

这种方式默认推送的就是当前分支中的提交内容。

拉取指定分支的项目代码

git pull origin master

拉取默认分支

git pull 

关于分支,我们下一节会详细的说到。

分支

分支的基本概念

前面我们已经说过 HEAD 它类似于指针和索引的概念,在git中,HEAD 指向的是分支,分支用于保存提交结果,并面向最后的推送。

git默认的分支是 master 分支,在没有其它分支的情况下,所有的提交操作都会被保存保存到master分支上,最终这个分支的时间线会不断的进行延伸。但不变的是 HEAD 指向mastermaster再面向最后的推送。

分支的优势在于其类似于一个平行独立的个体,不同的分支可以用来保存不同的提交和推送结果,从而避免在开发时产生的代码冲突。

分支的常用命令

下面是分支常用的命令集合

创建分支

git branch <branchname>

切换分支

git checkout <branchname>

创建并切换分支

git checkout -b <branchname>

查看分支

查看本地分支
git branch
查看远程分支

//查看所有分支
git branch -a
//查看远程分支
git branch -r

合并分支

fast forward 模式合并
git merge <branchname>
非fast forward 模式合并
git merge --no-ff -m "merge width no-ff" <branchname>

fast forward 与非 fast foward模式在于前者属于一种快速合并方式,不会保存历史记录,而后者会在合并时,创建commit提交,从而保留被合并分支之前的记录,通过 git log --graph --pretty=oneline --abbrev-commit 命令可以查看--no-ff模式下的合并提交记录。

删除分支

一般删除
git git branch -d <branchname>
强行删除
git branch -D <branchName>
删除远程分支
git branch -r -a <branchName>

分支的注意事项

git 中的分支分为本地分支与远程分支,本地分支就是使用者自己在本地仓库中创建的分支,所以远程分支便是使用者自己在远程仓库中建立的分支,具体示例如下图:

先简单的介绍本地分支的操作流程,当我们在本地的git中创建一个 dev 的分支时,在没有切换下,HEAD 依然指向的是默认的分支 master ,当我们通过 git checkout dev 切换到 dev 分支时,HEAD 便会指向 dev 分支。然后我们进行的提交操作,都会保存到 dev 分支中再面向最后的推送(push),如果此时再通过git命令切换到 master 分支,那么HEAD就会自然的再指向 master, 然后 master 面向提交,当我们在 master 基础上合并 dev 分支时,git就会将dev分支上的参数信息合并到master上,这样master上就可以看到之前的dev分支的所有提交内容了。

接着再介绍一下远程分支的概念,虽然我们说git中的分支分为“本地分支”与“远程分支”,但实际上这个区分并不突出,这是因为我们在本地git仓库中创建的分支,只要本地仓库origin与远程仓库origin是相连的情况下,git会自动帮我们将本地与远程同名的分支进行关联,除此之外,在进行 fetch 操作时,git也会将本地的分支自动同步到远程仓库总。除此之外当我们 直接切换本地不存在但远程存在的分支时,git都会自动帮我们创建,切换并进行关联。
示例:

git checkout dev
//如果远程仓库存在dev分支,git会自动帮我们创建,关联与切换dev分支

需要注意的一点是,在本地同一个机器下创建的多个分支,其工作区中的文件是可以共享的,但是一旦该文件在某个分支中推送到了远程对应的分支时,那么该文件边只会是该分支独有的文件。

最后,关于分支的使用和注意事项,我做了几条简单的总结:

1.  远程分支中的内容是独立的,但是对于同一个机器的本地分支而言,所创建的资源文件都是共享的。但是如果本地分支中的内容,推送到对应的远程文件,那么该内容在其它分支将会不可见。
2.  每个分支都会保存自己的提交状态。
3.  分支面向最后的推送,而推送的内容不会影响其它分支下的同文件。但是一旦分支合并后,那么在参与合并的这几个分支下,该文件便会是相同的内容。
4.  当前的分支如果文件发生了变更时,是无法进行分支切换的,只有提交操作后才能够切换。

分支冲突

分支再合并的时候,有可能会产生冲突。
冲突的产生是因为在合并的时候,不同分支修改了相同的位置。所以在合并的时候git不知道那个到底是你想保留的,所以就提出疑问(冲突提醒)让你自己手动选择想要保留的内容,从而解决冲突。
错误提示如下:

[email protected] MINGW64 /d/work/test (master)
$ git merge feature
Auto-merging branch.txt
CONFLICT (content): Merge conflict in branch.txt
Automatic merge failed; fix conflicts and then commit the result.

[email protected] MINGW64 /d/work/test (master|MERGING)
$ git status
On branch master
Your branch is ahead of ‘origin/master‘ by 1 commit.
  (use "git push" to publish your local commits)
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)

        both modified:   branch.txt

no changes added to commit (use "git add" and/or "git commit -a")

解决冲突的方法也很简单,通过 git bash 自带的命令工具,修改冲突的文件内容即可,然后再重新提交,推送!

示例:

//第一步:
git checkout -b feature
vi readme.txt // 修改内容为 feature branch
git commit -a -m ‘commit‘

git checkout master
vi readme.txt //修改内容为 feature branch & master branch
git commit -a -m ‘commit‘

//第二步:
git merge feature
// 此时应该会提示冲突(CONFLICT)
git status
// 查看状态会看到更多的冲突提示信息。

//第三步:重新编辑冲突文件,然后提交 [略]

多人协作

分支可以很好的帮助我们进行多人协同开发,我们知道每个分支可以保存不同的提交结果,我们可以将正式版保存在一个分支下,将测试版的提交保存到另一个分支下,还可以让每个开发者都有自己的分支,每个开发者都在自己的分支上负责自己的工作,最后再合并分支,而这些分支的特性便为多人协同开发提供了坚强的支撑基础。
前面我们也学到了分支的常规操作,以及分支冲突的解决,这里我们就简单的来说下,多人协作下的分支开发是一种什么样的情况。

首先,在多人协作开发中,分支应该分为三种,一种是版本分支(master),专门用于发布稳定的版本,二是开发分支(dev),开发人员的代码会不断的合并到该分支,最后便是用户分支(user-*)每个开发者都会有自己的工作分支。

具体如图所示:

master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;
你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了。

多人协作时,大家都会往master和dev分支上推送各自的修改。
现在,模拟一个你的小伙伴,可以在另一台电脑(注意要把SSH Key添加到GitHub)或者同一台电脑的另一个目录下克隆:

$ git clone git@xxxxx.com/test.git
Cloning into ‘learngit‘...
remote: Counting objects: 46, done.
remote: Compressing objects: 100% (26/26), done.
remote: Total 46 (delta 16), reused 45 (delta 15)
Receiving objects: 100% (46/46), 15.69 KiB | 6 KiB/s, done.
Resolving deltas: 100% (16/16), done.

当你的小伙伴从远程库clone时,默认情况下,你的小伙伴只能看到本地的master分支。不信可以用git branch命令看看:

$ git branch
* master

现在,你的小伙伴要在dev分支上开发,就必须创建远程origin的dev分支到本地,于是他用这个命令创建本地dev分支:

$ git checkout -b dev origin/dev

实际上,如果我们直接git chekout dev 也是可以自动创建,切换并关联dev分支的。
现在,他就可以在dev上继续修改,然后,时不时地把dev分支push到远程:

git commit -m "add /usr/bin/env"

总的来说,多人协作的工作模式通常是这样:

  • 首先,可以试图用git push origin branch-name推送自己的修改;
  • 如果推送失败,则因为远程分支比你的本地更新,需要先用git pull试图合并;
  • 如果合并有冲突,则解决冲突,并在本地提交;
  • 没有冲突或者解决掉冲突后,再用git push origin branch-name推送就能成功!

如果git pull提示“no tracking information”,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream branch-name origin/branch-name。

这就是多人协作的工作模式,一旦熟悉了,就非常简单。

bug 分支

首先让我们代入一个问题去思考!如何在一个多人协作的开发情况下去修复一个bug呢?我想,我们会想到的是,现本地 pull 一下,然后找到那个bug所在的文件,然后修改bug,最后在与dev分支合并分支。
是的,基本的步骤就是如此,但现实情况却总是那么骨感,比如你现在已经在你当前的分支上进行某项功能的开发,而且离你能完成的时间最少还需要1天,但是这个bug又需要立刻修掉,这种情况下你便不能直接用你当前的分支去修改,然后合并了,这会将你正在进行的工作也合并到dev,那么我们应该怎么去修复bug呢?
思路是一样的,这种情况下,我们依然通过分支去修bug,但是我们会在暂存当前分支的工作状态,然后新建并切换一个临时分支去修复bug,然后与dev进行分支合并,最终再恢复之前工作状态。

首先检查自己工作分支的状态

[email protected] MINGW64 /d/work/test (shentao)
$ git status
On branch shentao
Untracked files:
  (use "git add <file>..." to include in what will be committed)

        shenguotao2.txt

nothing added to commit but untracked files present (use "git add" to track)

发现当前分支有更改,但是目前不需要合并到开发环境,所以保存工作状态,建立临时分支

Administrator@LS1412PC0008 MINGW64 /d/work/test (shentao)
$ git stash
No local changes to save

Administrator@LS1412PC0008 MINGW64 /d/work/test (shentao)
$ git checkout -b issue-01
Switched to a new branch ‘issue-01‘

然后切换到临时分支,再去修改bug文件,这里我随便添加点内容,然后切换到dev分支

Administrator@LS1412PC0008 MINGW64 /d/work/test (issue-01)
$ vi shenguotao.txt

Administrator@LS1412PC0008 MINGW64 /d/work/test (issue-01)
$ git add *

Administrator@LS1412PC0008 MINGW64 /d/work/test (issue-01)
$ git commit -m ‘repair bug‘
[issue-01 af1d81f] repair bug
 1 file changed, 1 insertion(+)

Administrator@LS1412PC0008 MINGW64 /d/work/test (issue-01)
$ git checkout dev
Switched to branch ‘dev‘

再将临时分支与dev分支进行分支合并,然后删除临时分支

[email protected] MINGW64 /d/work/test (dev)
$ git merge issue-01
Updating 587b031..af1d81f
Fast-forward
 shenguotao.txt | 1 +
 1 file changed, 1 insertion(+)

[email protected] MINGW64 /d/work/test (dev)
$ git branch -d issue-01
Deleted branch issue-01 (was af1d81f).

最后我们再切换到自己工作的分支,查看当前的分支状态是干净的,所以要恢复之前的工作状态

[email protected] MINGW64 /d/work/test (shentao)
$ git status
On branch dev
nothing to commit, working tree clean

[email protected] MINGW64 /d/work/test (shentao)
$ git stash pop
On branch dev
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        new file:   shenguotao2.txt

Dropped refs/[email protected]{0} (4323cae5c4f94b6df6c10b3abcacc71c0cf47f01)

这里的重点一是掌握通过分支解决bug的思路,二是掌握保存,删除,恢复分支工作状态的命令

** 保存当前分支的工作状态**
git stash

** 查看当前分支的工作状态列表**
git stash list

恢复分支最新的工作状态
git stash pop

恢复分支指定的工作状态
git stash appy [email protected]{0}
注:该命令可结合 git stash list 使用

删除分支状态
git stash drop

标签

标签的概念

git 中的tag是标签的意思,它就像是指向某个commit的指针,用于跟某个具体的提交绑定在一起。
git 有commit,为什么还要引入tag?

“请把上周一的那个版本打包发布,commit号是6a5819e...”
“一串乱七八糟的数字不好找!”
如果换一个办法:
“请把上周一的那个版本打包发布,版本号是v1.2”
“好的,按照tag v1.2查找commit就行!”

所以tag 又类似于别名,因此在发布一个版本时,我们通常先在版本库中打一个标签(tag),这样,就唯一确定了打标签时刻的版本。

tag 与 branch的区别就在与一个是标识commit另一个则是存储commit,所以标签的数量是未知的,而分支的数量是可知的。

标签的常用命令

下面是关于tag的相关操作命令

创建标签

git tag <tagName>

注意:默认的是为最新的 commit 创建tag。

为指定的commit创建标签

git tag <tagName> [commitID]
//示例:git tag v0.9 6224937

创建带注释说明的标签

git tag -a <tagName> -m ‘note content‘

查看标签

git tag

查看指定标签的信息

git show <tagName>

删除标签

git tag -d <tagName>

推送标签到远程

git push origin <tagName>

将本地所有标签推送到远程

git push origin --tags

删除远程标签

git push origin :refs/tags/v0.9

自定义

用户信息与加密key

在我们本地的git中,可以配置使用者的相关信息

git config --global user.name "shenguotao"
git config --global user.email "[email protected]"

然后可以通过
git config --list
去查看信息。

如果我们担心在拉取或推送远程仓库时,会有人冒充,那么便可以使用ssh方式,并将自己的公钥上传到指定服务器上,供第一次链接时进行验证使用。

首先生成本地电脑的私钥与公钥。

$ ssh-keygen -t rsa -C "[email protected]"

你需要把邮件地址换成你自己的邮件地址,然后一路回车即可,并无需设置密码。
如果一切顺利的话,可以在用户主目录里找到 .ssh 目录,里面有id_rsa和 id_rsa.pub 两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。
最后,登录的你github,打开“Account settings”,“SSH Keys”页面:
然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容便可。

为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。

当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。

最后友情提示,在GitHub上免费托管的Git仓库,任何人都可以看到喔(但只有你自己才能改)。所以,不要把敏感信息放进去。

命令语法着色

可以在config中配置相关命令,使语法着色,让命令更加突出。

git config --global color.ui true

文件忽略

对于不想提交的文件,我们可以建一个.gitignore文件来设置那些文件是要被忽略的。然后再把.gitignore文件提交上去即可。
一般.gitignore文件编写如下示例:

//.gitignore
example.png //忽略指定的文件
test //忽略整个目录
*.md //忽略所有的.md文件

如果想强制将.gitignore文件中设定的忽略文件提交到版本库中,可以使用以下命令:

git add -f <fileName>

如果想查看某个忽略声明在.gitignore文件的那一行,可以使用如下命令:

git check-ignore -v example.png

自定义命令

如果你觉得git默认的命令过于繁杂难以记忆,那么你可以自定义git的命令

git config --global alias.st status

其它的有:

$ git config --global alias.co checkout
$ git config --global alias.ci commit
$ git config --global alias.br branch

说明:--global 用于设置该配置是否对全局都产生作用。

超推荐:

git config --global alias.lg "log --color --graph --pretty=format:‘%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset‘ --abbrev-commit"

修改配置文件

git中的配置信息是保存在配置文件中的,配置文件根绝作用范围不同,分为当前版本库的配置文件,其路径,就是:.git/config ,另一个则是全局的git配置文件,是对所有的版本库都起作用,它默认在操作系统的用户目录,文件名为 ‘.gitconfig‘ 。

cd .git
cat config
//-----
cd c:/Users
cat .gitconfig

在配置文件中,就可以修改 remote,alias等吧。

git常见问题

空的git仓库不能提交到远程库

[email protected] MINGW64 /d/work/test (master)
$ git push -u origin master
error: src refspec master does not match any.
error: failed to push some refs to ‘https://github.com/shenguotao2015/fdasfdsafsaf.git‘

解决方法:建一个readme文件!

git报错无法push
这是由于远程repository和我本地的repository冲突造成,通常发生在多人协作的开发过程中

$git push
To gitkt:abroadweb
![rejected] master -> master(non-fast-forward)
error:failed to push some refs to ‘gitkt:abroadweb‘
hint:Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: ‘git pull..‘) before pushing again ...

解决方法:
1.使用强制push的方法:
git push -u origin master -f
这样会使远程修改丢失,一般是不可取的

2.push前先将远程repository修改pull下来
git pull origin master
git push -u origin master

3.若不想merge远程和本地修改,可以先创建新的分支:
git branch [name]
git push -u origin [name]

多人协作的开发过程,一般推荐熟练使用分支功能来进行代码的托管,这样就会避免冲突的发生。

postBuffer 超出

error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: unpack-objects failed

错误原因:
postBuffer是请求缓存区的意思,它的功能是当我们去 git clone 某个项目的时候,实际上git会有一个临时的缓存区去保存克隆的内容,当确定所有的内容都下载好后,才会保存到本地,但是如果这个缓存区设置的大小小于项目本身大小时,就会产生以上错误。

解决方法:
将postBuffer的大小设置的更大一些。

git config --global http.postBuffer 524288000

这里我们就讲postBuffer的缓存区设置为500MB


强烈推荐廖雪峰的git教程
http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000
linux的常用命令
http://www.cnblogs.com/laov/p/3541414.html
vi的百度百科
http://baike.baidu.com/item/Vi/8987313

http://www.cnblogs.com/HCJJ/p/6650038.html

时间: 2024-10-13 17:30:11

git 入门宝典的相关文章

【Git入门之四】操作项目

[Git入门之四]操作项目 - JackyStudio - 博客频道 - CSDN.NET 1.查看操作日记 <git log>用于查看操作日记详情.因为Git是分布式的,采用SHA1这样的版本号可有效的防止版本冲突. [cpp]?view plaincopy ? #查看操作日记,底下那串长长的数据就是SHA1?ID,表示当前版本号?? $Snbsp;git?log?? commit?aea0365712908805bc28540b4db9fd2f15360a8b?? Author:?Jack

【Git入门之十二】DIY Git

[Git入门之十二]DIY Git - JackyStudio - 博客频道 - CSDN.NET Git的配置是很有学问的,如果弄懂它,将对你帮助很大. 1.用户配置 这是全局的. ? [cpp]?view plaincopy ? #设置用户名?? $Snbsp;git?config?--global?user.name?"Jacky"?? ?? #设置邮箱?? $Snbsp;[email protected]?? ? 2.设置默认编辑器 在需要输入文本信息时调用,比如之前的reba

【Git入门之十三】Ubuntu和git

[Git入门之十三]Ubuntu和git - JackyStudio - 博客频道 - CSDN.NET 之前我们都是在Windows平台下操作git.现在我们改用Ubuntu试一试吧!先准备好Ubuntu或者Linux系统吧.这里采用13.04版本虚拟机环境 1.Ubuntu下使用git 打开终端(Ctrl+Alt+T).Ubuntu下就没有git bash了,都是使用terminal. 1.1.安装SSH ? [cpp]?view plaincopy ? sudo?apt-get?insta

【Git入门之十四】Git GUI

[Git入门之十四]Git GUI - JackyStudio - 博客频道 - CSDN.NET 文章都快写完了,Git GUI才浮出水面,很多人要骂我,这么方便的东西怎么不早拿出来. 当然命令行和图形界面各有千秋,个人觉得命令行更能让人清楚的掌握整个项目的代码线.当然萝卜青菜各有所爱,Windows,Linux也是一样.喜欢什么客官您挑.本文只做简单介绍. 1.Git GUI有什么? 霸气测漏的右键菜单和可视化管理界面. 2.初始化仓库 新建一个文件夹叫JackyGUI,右键点击Git In

git 入门操作指令

git add [commit file list] 将已经修改的代码添加索引 git commit -m [commit message] 将已经索引的代码修改提交至本地的库 git push origin [branch_name] 将分支 branch_name 的代码推送至服务器 git pull origin [branch_name] 获取分支 branch_name上的最新代码 git pull --rebase origin [branch_name] 将当前 branch 从

版本控制工具 GIT入门教程

GIT 在团队中的中作流程 1.每个程序员在自己的分支上进行开发 2.主程序猿/Leader合并程序员程序 3.程序员之间也可以对一下提交冲突进行合并 下载和安装 GIT官方网址:http:// git - scm.com 具体怎么装,一直点下一步就是了(PS:windows) 创建一个库 启动git bash,由于是刚刚安装,所以还没有任何工程库 创建一个目录 mkdir gitproject 进入gitproject目录 cd gitproject 初始化工程库 git init 系统给出提

git入门(1.历史)

git入门(1.历史) git入门(2.基础) git入门(3.文件操作) git入门(4.提交与历史) git入门(5.分支) git入门(6.repo) 版本控制 版本控制是什么已不用在说了,就是记录我们对文件.目录或工程等的修改历史,方便查看更改历史,备份以便恢复以前的版本,多人协作... 一.原始版本控制 最原始的版本控制是纯手工的版本控制:修改文件,保存文件副本.有时候偷懒省事,保存副本时命名比较随意,时间长了就不知道哪个是新的,哪个是老的了,即使知道新旧,可能也不知道每个版本是什么内

Git入门(三)——没有版本控制意识的程序员不是一个好的程序员

之前所讲的都是"自娱自乐",自己管理自己的项目.本篇主要是Git入门的尾声,也是最为精华的一部分,即利用Git进行版本控制,进行"团队协作开发",也会介绍分支合并以及合并冲突时常见的处理方法. 五.团队协作流程 1. 基本流程 (1) 创建一个分支 当你在开发一个项目的时候,一般在同一时刻你会同时展开多个想法,其中一些比较成熟了,另一些还是很初级的.有了分支就可以很好地来进行管理了.当你在项目中创建一个分支的时候,你可能就是正在搭建一个可以尝试新想法的环境.你在新分

深入学习:Windows下Git入门教程(下)

声明:由于本人对于Git的学习还处于摸索阶段,对有些概念的理解或许只是我断章取义,有曲解误导的地方还请见谅指正! 一.分支 1.1分支的概念. 对于的分支的理解,我们可以用模块化这个词来解释:在日常工作中,一个项目的开发模式往往是模块化,团队协作式的开发.这样我们项目的进度可以称得上多核并发式的开发了.这种模块化的开发要求我们尽可能的高内聚低耦合以免造成一只胳膊没了整个人都废了的局面.因此在所有的版本控制器对代码进行管理的时候都引入了分支这个概念.那么分支是什么呢? 分支是相对于主干来说的,或者