社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
Git是目前世界上最先进的分布式版本控制系统。
Linus在1991年创建了开源的Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在世界各地为Linux编写代码,那Linux的代码是如何管理的呢?
事实是,在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码!
不过,到了2002年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是Linus选择了一个商业的版本控制系统BitKeeper,BitKeeper的东家BitMover公司出于人道主义精神,授权Linux社区免费使用这个版本控制系统。
安定团结的大好局面在2005年就被打破了,原因是Linux社区牛人聚集,不免沾染了一些梁山好汉的江湖习气。开发Samba的Andrew试图破解BitKeeper的协议(这么干的其实也不只他一个),被BitMover公司发现了(监控工作做得不错!),于是BitMover公司怒了,要收回Linux社区的免费使用权。
Linus可以向BitMover公司道个歉,保证以后严格管教弟兄们,嗯,这是不可能的。实际情况是这样的:
Linus花了两周时间自己用C写了一个分布式版本控制系统,这就是Git!一个月之内,Linux系统的源码已经由Git管理了!牛是怎么定义的呢?大家可以体会一下。
Git迅速成为最流行的分布式版本控制系统,尤其是2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。
Linus一直痛恨的CVS及SVN都是集中式的版本控制系统,而Git是分布式版本控制系统,集中式和分布式版本控制系统有什么区别呢?
先说集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。
集中式版本控制系统最大的毛病就是必须联网才能工作,如果在局域网内还好,带宽够大,速度够快,可如果在互联网上,遇到网速慢的话,可能提交一个10M的文件就需要5分钟,这还不得把人给憋死啊。
那分布式版本控制系统与集中式版本控制系统有何不同呢?首先,分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。
和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。
在实际使用分布式版本控制系统的时候,其实很少在两人之间的电脑上推送版本库的修改,因为可能你们俩不在一个局域网内,两台电脑互相访问不了,也可能今天你的同事病了,他的电脑压根没有开机。因此,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
当然,Git的优势不单是不必联网这么简单,后面我们还会看到Git极其强大的分支管理,把SVN等远远抛在了后面。
在Windows上使用Git,可以从Git官网直接下载安装程序,(网速慢的同学请移步国内镜像),然后按默认选项安装即可。
安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!
安装完成后,还需要最后一步设置,在命令行输入:
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。你也许会担心,如果有人故意冒充别人怎么办?这个不必担心,首先我们相信大家都是善良无知的群众,其次,真的有冒充的也是有办法可查的。
注意git config
命令的--global
参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置,当然也可以对某个仓库指定不同的用户名和Email地址。
首先,你可以试着输入git
,看看系统有没有安装Git:
$ git
The program 'git' is currently not installed. You can install it by typing:
sudo apt-get install git
像上面的命令,有很多Linux会友好地告诉你Git没有安装,还会告诉你如何安装Git。
如果你碰巧用Debian或Ubuntu Linux,通过一条sudo apt-get install git
就可以直接完成Git的安装,非常简单。
如果是其他Linux版本,可以直接通过源码安装。先从Git官网下载源码,然后解压,依次输入:./config
,make
,sudo make install
这几个命令安装就好了。
learngit
什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。
所以,创建一个版本库非常简单,首先,选择一个合适的地方,创建一个空目录:
$ mkdir learngit
$ cd learngit
$ pwd
/Users/xiaokai/learngit
pwd
命令用于显示当前目录。在我的电脑上,这个仓库位于/c/Users/xiaokai/learngit
。
如果你使用Windows系统,为了避免遇到各种莫名其妙的问题,请确保目录名(包括父目录)不包含中文。
xiaokai@MateBook-X-Pro MINGW64 ~
$ pwd
/c/Users/xiaokai
xiaokai@MateBook-X-Pro MINGW64 ~
$ mkdir learngit
xiaokai@MateBook-X-Pro MINGW64 ~
$ cd learngit/
xiaokai@MateBook-X-Pro MINGW64 ~/learngit
$ pwd
/c/Users/xiaokai/learngit
xiaokai@MateBook-X-Pro MINGW64 ~/learngit
$ git init
Initialized empty Git repository in C:/Users/xiaokai/learngit/.git/
所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
不幸的是,Microsoft的Word格式是二进制格式,因此,版本控制系统是没法跟踪Word文件的改动的,前面我们举的例子只是为了演示,如果要真正使用版本控制系统,就要以纯文本方式编写文件。
因为文本是有编码的,比如中文有常用的GBK编码,日文有Shift_JIS编码,如果没有历史遗留问题,强烈建议使用标准的UTF-8编码,所有语言使用同一种编码,既没有冲突,又被所有平台所支持。
使用Windows的童鞋要特别注意:
千万不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队使用了一个非常弱智的行为来保存UTF-8编码的文件,他们自作聪明地在每个文件开头添加了0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如,网页第一行可能会显示一个“?”,明明正确的程序一编译就报语法错误,等等,都是由记事本的弱智行为带来的。建议你下载Notepad++代替记事本,不但功能强大,而且免费!记得把Notepad++的默认编码设置为UTF-8 without BOM即可:
现在我们编写一个readme.txt
文件,内容如下:
Git is a version control system.
Git is free software.
一定要放到learngit
目录下(子目录也行),因为这是一个Git仓库,放到其他地方Git再厉害也找不到这个文件。
和把大象放到冰箱需要3步相比,把一个文件放到Git仓库只需要两步。
第一步,用命令git add
告诉Git,把文件添加到仓库:
$ git add readme.txt
执行上面的命令,没有任何显示,这就对了,Unix的哲学是“没有消息就是好消息”,说明添加成功。
第二步,用命令git commit
告诉Git,把文件提交到仓库:
$ git commit -m "wrote a readme file"
[master (root-commit) eaadf4e] wrote a readme file
1 file changed, 2 insertions(+)
create mode 100644 readme.txt
简单解释一下git commit
命令,-m
后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。
git commit
命令执行成功后会告诉你,1 file changed
:1个文件被改动(我们新添加的readme.txt文件);2 insertions
:插入了两行内容(readme.txt有两行内容)。
为什么Git添加文件需要add
,commit
一共两步呢?因为commit
可以一次提交很多文件,所以你可以多次add
不同的文件,比如:
$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."
首先找到目标位置,创建本地物理位置:
$ mkdir learngit
$ cd learngit
使用git init
命令初始化版本库
$ git init
创建文件,并保存到learngit
这个文件下
$ gedit readme.txt
使用git add
命令上传文件
$ git add readme.txt
使用git commit
命令添加说明信息
$ git commit -m "在这里添加每次上传改变了什么,用引号括起来"
git status
查看仓库状态在修改了readme.txt
之后,不确定是否是最新的内容,怎么查看呢:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
no changes added to commit (use "git add" and/or "git commit -a")
运行git status
查看结果,这个命令可以让我们时刻掌握仓库当前的状态,上面的命令提示说已经被modified修改过了,但是changes not staged for commit,还没有提交。
git diff
寻找差异虽然Git告诉我们readme.txt
被修改了,但如果能看看具体修改了什么内容,自然是很好的。比如你休假两周从国外回来,第一天上班时,已经记不清上次怎么修改的readme.txt
,所以,需要用git diff
这个命令看看:
$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 46d49bf..9247db6 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,2 +1,2 @@
-Git is a version control system.
+Git is a distributed version control system.
Git is free software.
git diff
顾名思义就是查看difference,显示的格式正是Unix通用的diff格式,可以从上面的命令输出看到,我们在第一行添加了一个distributed
单词。
git add commit -m
提交修改知道了对readme.txt
作了什么修改后,再把它提交到仓库就放心多了,提交修改和提交新文件是一样的两步,第一步是git add
:
$ git add readme.txt
同样没有任何输出。在执行第二步git commit
之前,我们再运行git status
看看当前仓库的状态:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: readme.txt
git status
告诉我们,将要被提交的修改包括readme.txt
,下一步,就可以放心地提交了:
$ git commit -m "add distributed"
[master e475afc] add distributed
1 file changed, 1 insertion(+), 1 deletion(-)
提交后,我们再用git status
命令看看仓库的当前状态:
$ git status
On branch master
nothing to commit, working tree clean
Git告诉我们当前没有需要提交的修改,而且,工作目录是干净(working tree clean)的。
git status
命令。git diff
命令。git add
和git commit -m
命令。现在,你已经学会了修改文件,然后把修改提交到Git版本库,现在,再练习一次,修改readme.txt文件如下:
Git is a distributed version control system.
Git is free software distributed under the GPL.
然后尝试提交:
$ git add readme.txt
$ git commit -m "append GPL"
[master 1094adb] append GPL
1 file changed, 1 insertion(+), 1 deletion(-)
像这样,你不断对文件进行修改,然后不断提交修改到版本库里,就好比玩RPG游戏时,每通过一关就会自动把游戏状态存盘,如果某一关没过去,你还可以选择读取前一关的状态。有些时候,在打Boss之前,你会手动存盘,以便万一打Boss失败了,可以从最近的地方重新开始。Git也是一样,每当你觉得文件修改到一定程度的时候,就可以“保存一个快照”,这个快照在Git中被称为commit
。一旦你把文件改乱了,或者误删了文件,还可以从最近的一个commit
恢复,然后继续工作,而不是把几个月的工作成果全部丢失。
现在,我们回顾一下readme.txt
文件一共有几个版本被提交到Git仓库里了:
版本1:wrote a readme file
Git is a version control system.
Git is free software.
版本2:add distributed
Git is a distributed version control system.
Git is free software.
版本3:append GPL
Git is a distributed version control system.
Git is free software distributed under the GPL.
git log
查看记录当然了,在实际工作中,我们脑子里怎么可能记得一个几千行的文件每次都改了什么内容,不然要版本控制系统干什么。版本控制系统肯定有某个命令可以告诉我们历史记录,在Git中,我们用git log
命令查看:
xiaokai@MateBook-X-Pro MINGW64 ~/learngit (master)
$ git log
commit c3796d3a6bcdd90f78fe4b8a3e06d1c59f1fdaa1 (HEAD -> master)
Author: xiaokai1996 <2019+xiaokai1996@users.noreply.github.com>
Date: Fri May 31 17:30:38 2019 +0800
add GPL
commit 16ac4d39fae4be747466973505b90d5d11429865
Author: xiaokai1996 <2019+xiaokai1996@users.noreply.github.com>
Date: Fri May 31 10:58:19 2019 +0800
add distributed
commit 512af4a9fa5c659a73b4adfa792223bc418f4fbf
Author: xiaokai1996 <2019+xiaokai1996@users.noreply.github.com>
Date: Fri May 31 10:32:55 2019 +0800
wrote a readme file
如果觉得非常混乱,可以使用命令git log --pretty=oneline
:
xiaokai@MateBook-X-Pro MINGW64 ~/learngit (master)
$ git log --pretty=oneline
c3796d3a6bcdd90f78fe4b8a3e06d1c59f1fdaa1 (HEAD -> master) add GPL
16ac4d39fae4be747466973505b90d5d11429865 add distributed
512af4a9fa5c659a73b4adfa792223bc418f4fbf wrote a readme file
git reset
回退版本好了,现在我们启动时光穿梭机,准备把readme.txt
回退到上一个版本,也就是add distributed
的那个版本,怎么做呢?
首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD
表示当前版本,也就是最新的提交1094adb...
(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^
,上上一个版本就是HEAD^^
,当然往上100个版本写100个^
比较容易数不过来,所以写成HEAD~100
。
使用git reset
命令把版本库回退到上一个add distributed
的版本:
xiaokai@MateBook-X-Pro MINGW64 ~/learngit (master)
$ git reset --hard HEAD^
HEAD is now at 16ac4d3 add distributed
使用cat
命令检查:
$ cat readme.txt
Git is a ditribution version control system.
Git is free software.
还可以继续还原到上一个版本,不过,这时候再用git log
查看一下版本库的状态:
xiaokai@MateBook-X-Pro MINGW64 ~/learngit (master)
$ git reset --hard 512a
HEAD is now at 512af4a wrote a readme file
xiaokai@MateBook-X-Pro MINGW64 ~/learngit (master)
$ git log
commit 512af4a9fa5c659a73b4adfa792223bc418f4fbf (HEAD -> master)
Author: xiaokai1996 <2019+xiaokai1996@users.noreply.github.com>
Date: Fri May 31 10:32:55 2019 +0800
发现只有一个版本了!好比穿梭回来,但是已经回不去了,怎么办?
git reflog
检查回退记录办法其实还是有的,只要上面的命令行窗口还没有被关掉,你就可以顺着往上找啊找啊,找到那个append GPL
的commit id
是c379...
,于是就可以指定回到未来的某个版本:
$ git reset --hard c379
HEAD is now at c3796d3 add GPL
版本号没必要写全,前几位(一般4位)就可以了,Git会自动去找。当然也不能只写前一两位,因为Git可能会找到多个版本号,就无法确定是哪一个了。
Git的版本回退速度非常快,因为Git在内部有个指向当前版本的HEAD
指针,当你回退版本的时候,Git仅仅是把HEAD从指向append GPL
:
┌────┐
│HEAD│
└────┘
│
└──> ○ append GPL
│
○ add distributed
│
○ wrote a readme file
改为指向add distributed
:
┌────┐
│HEAD│
└────┘
│
│ ○ append GPL
│ │
└──> ○ add distributed
│
○ wrote a readme file
然后顺便把工作区的文件更新了。所以你让HEAD
指向哪个版本号,你就把当前版本定位在哪。
现在,你回退到了某个版本,关掉了电脑,第二天早上就后悔了,想恢复到新版本怎么办?找不到新版本的commit id
怎么办?
在Git中,总是有后悔药可以吃的。当你用$ git reset --hard HEAD^
回退到add distributed
版本时,再想恢复到append GPL
,就必须找到append GPL
的commit id。Git提供了一个命令git reflog
用来记录你的每一次命令:
$ git reflog
512af4a (HEAD -> master) HEAD@{0}: reset: moving to 512a
c3796d3 HEAD@{1}: reset: moving to c379
16ac4d3 HEAD@{2}: reset: moving to HEAD^
c3796d3 HEAD@{3}: commit: add GPL
16ac4d3 HEAD@{4}: commit: add distributed
512af4a (HEAD -> master) HEAD@{5}: commit (initial): wrote a readme file
终于舒了口气,从输出可知,append GPL
的commit id是c3796d3
,现在,你又可以乘坐时光机回到未来了。
git log
命令。git reset --hard commit_id
命令,其中HEAD
就表示当前版本。git reflog
命令。working tree
电脑目录里能看到的就是工作区:
repository
工作区有一个隐藏目录.git
,这个不算工作区,而是Git的版本库。
Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master
,以及指向master
的一个指针叫HEAD
。
分支和HEAD
的概念我们以后再讲。
前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:
第一步是用git add
把文件添加进去,实际上就是把文件修改添加到暂存区;
第二步是用git commit
提交更改,实际上就是把暂存区的所有内容提交到当前分支。
因为我们创建Git版本库时,Git自动为我们创建了唯一一个master
分支,所以,现在,git commit
就是往master
分支上提交更改。
你可以简单理解为,需要提交的文件修改通通放到暂存区,然后,一次性提交暂存区的所有修改。
俗话说,实践出真知。现在,我们再练习一遍,先对readme.txt
做个修改,比如加上一行内容:
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git has a mutable index called stage.
然后,在工作区新增一个LICENSE
文本文件(内容随便写)。
先用git status
查看一下状态:
$ git status
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: readme.txt
Untracked files:
(use "git add <file>..." to include in what will be committed)
LICENSE.txt
Git非常清楚地告诉我们,readme.txt
被修改了,而LICENSE
还从来没有被添加过,所以它的状态是Untracked
。
现在,使用两次命令git add
,把readme.txt
和LICENSE
都添加后,用git status
再查看一下:
$ git status
On branch master
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
new file: LICENSE.txt
modified: readme.txt
现在,暂存区的状态就变成这样了:
所以,git add
命令实际上就是把要提交的所有修改放到暂存区(Stage),然后,执行git commit
就可以一次性把暂存区的所有修改提交到分支。
$ git commit -m "understand how stage works"
[master 587519b] understand how stage works
2 files changed, 2 insertions(+), 1 deletion(-)
create mode 100644 LICENSE.txt
一旦提交后,如果你又没有对工作区做任何修改,那么工作区就是“干净”的:
$ git status
On branch master
nothing to commit, working tree clean
现在版本库变成了这样,working tree
暂存区就没有任何内容了:
working space
--> working tree
--> git repository
,这两个箭头的过程命令,分别是git add
和git commit -m <discripion>
。git add
是不可以直接执行git commit -m <discription>
命令的。小结
working space
工作区的内容,想直接丢弃,直接使用git checkout -- file
命令丢弃更改。working space
工作区的内容,且已经提交到working tree
暂存区,需要使用git reset HEAD <file>
命令,先从git repository
版本库中恢复最新版本到暂存区,然后使用git checkout -- file
命令,将工作区中的修改丢弃。working space
工作区的内容,且已经提交到working tree
暂存区,并且已经使用git commit -m [discripition]
提交到版本库。先使用git log
命令查看提交历史,然后使用get reset
命令进行版本回退,再执行2的步骤。小结
git rm <file>
命令从版本库中删除文件,本质上和git add <fie>
命令是一样的。然后使用git commit -m
命令提交更改,版本库里的内容和工作区里的内容会被一起删掉。git reset
命令回退版本,git status
发现暂存区和工作区里面的内容不一致,然后使用git checkout -- <file>
丢弃更改(恢复文件)。$ ssh-keygen -t rsa -C "1353437769@qq.com"
如果一切顺利的话,可以在用户主目录里找到.ssh
目录,里面有id_rsa
和id_rsa.pub
两个文件,这两个就是SSH Key的秘钥对,id_rsa
是私钥,不能泄露出去,id_rsa.pub
是公钥,可以放心地告诉任何人。
选择右上角用户头像 -> 菜单“修改资料”,然后选择“SSH公钥”,填写一个便于识别的标题,然后把用户主目录下的.ssh/id_rsa.pub
文件的内容粘贴进去:
首先在码云上创建一个learngit.git
的库,**注意在初始化的时候,不要往里面添加任何文件!**然后使用命令git remote add
远程关联:
git remote add origin git@gitee.com:liukai1996/learngit.git
如果已经关联了别的远程库,可以删除已有的库,再重新关联
git remote -v
git remote rm origin
git remote add orgin git@gitee.com:liukai1996/learngit.git
git push -u origin master
在gitee上新建一个空项目之后,会自动弹出如下界面:
Git 全局设置:
git config --global user.name "刘凯"
git config --global user.email "1353437769@qq.com"
创建 git 仓库:
mkdir learngit
cd learngit
git init
touch README.md
git add README.md
git commit -m "first commit"
git remote add origin git@gitee.com:liukai1996/learngit.git
git push -u origin master
已有仓库?
cd existing_git_repo
git remote add origin git@gitee.com:liukai1996/learngit.git
git push -u origin master
大部分时候,我们需要做的就是在自己的项目下分别输入:
cd existing_git_repo
git init
# 把所有的文件上传到repo版本库中
git add .
# 添加说明信息
git commit -m "add all files in this dir to the current repo"
首先登陆码云,新建一个新的仓库。
勾选Initialize this repository with a README
,自动创建一个README.md
文件。
下一步复制ssh
地址,使用git clone
克隆一个本地库。
注意,在克隆的时候,要注意:
pwd
看一下当前的工作目录,然后再使用git clone
命令大部分时候,我们需要做的就是在自己的项目下分别输入:
# 查看当前绑定的repo
git remote -v
# 绑定到现在的项目上
git remote add origin git@gitee.com:liukai1996/###.git
# 开始推送
git push -u origin master
git remote add origin git@server-name:path/repo-name.git
git push -u origin master
推送master所有分支的内容,之后使用git push
即可git push origin master
推送最新修改origin
可以分别改成github
和gitee
一开始,master
分支是一条线,master
指向最新的提交,然后使用一个HEAD
指针指向master
,每一次的提交,都会让master
分支线变长。
git add
git commit -m "description"
当我们创建一个分支dev
,就会新建一个指针dev
指向和master
相同的提交,再把HEAD
指向dev
,表示当前的分支在dev
上。
git branch dev
git checkout dev
# 或者用一条命令
git checkout -b dev
接下来,对工作区的修改和提交就是针对dev
的修改和提交了,每提交一次,dev
指针向前移动一步,而master
指针不变。
git branch
git add readme.txt
git commit -m "test a branch"
最后工作完成后,把dev
分支合并到master
上,让master
指向dev
的提交就完成了合并。
git checkout master
git merge dev
合并完成之后,可以删除dev
分支,最后只剩下一个master
分支。
git branch -d dev
小结
命令 | 说明 |
---|---|
git branch | 查看分支 |
git branch <name> | 创建分支 |
git checkout <name> | 切换分支 |
git checkout -b <name> | 创建的同时,切换分支 |
git merge <name> | 把分支合并到当前目录 |
git branch -d <name> | 删除分支 |
git push --set-upstream origin feature1
例如我们在一个新的分支上进行修改:
git checkout -b feature1
然后在feature
这个分支上修改提交
git add readme.txt
git commit -m "add something new"
切换到master
分支上继续修改
git checkout master
然后在master
分支上提交修改
git add readme.txt
git commit -m "ADD STH. NEW"
所以现在就变成了这样
接着执行快速合并
git checkout master
git merge feature1
提示错误:
$ 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: readme.txt
此时只能查看并修改readme.txt
里的内容然后再提交
然后使用git log --graph --pretty=oneline --abbrev-commit
命令查看合并情况
最后使用git branch -d feature1
删除分支。
小结
git merge <name>
失败,需要手动解决冲突,然后再提交合并git log --graph
命令可以图形化的方式查看合并图使用fast farword
模式有一个问题,就是在合并分支并删除分支后,分支信息就会丢失,所以更好的方式是使用--no-ff
模式去git merge
,同时会生成一个新的commit
,这样在历史分支上也能看出分支的信息。
首先创建并切换dev
分支,并修改提交
git checkout -b dev
git add readme.txt
git commit -m "add merge"
接着切换回master
主分支,进行合并,并且使用-m <discription>
提交
git checkout master
git merge --no-ff -m "merge with no-ff" dev
合并之后,再使用git log --graph --pretty=oneline --abbrev-commit
查看分支历史,最后看起来应该是这样
在实际开发中,master
分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;
那在哪干活呢?干活都在dev
分支上,也就是说,dev
分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev
分支合并到master
上,在master
分支发布1.0版本;
你和你的小伙伴们每个人都在dev
分支上干活,每个人都有自己的分支,时不时地往dev
分支上合并就可以了。
所以,团队合作的分支看起来就像这样:
小结
合并分支使用git merge --no-ff <name>
命令进行普通合并
修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时,先把工作现场git stash
一下,然后去修复bug,修复后,再git stash pop
,回到工作现场。
开发一个新feature,最好新建一个分支;
如果要丢弃一个没有被合并过的分支,可以通过git branch -D <name>
强行删除。
多人协作的工作模式通常是这样:
git push origin <branch-name>
推送自己的修改;git pull
试图合并;git push origin <branch-name>
推送就能成功!如果git pull
提示no tracking information
,则说明本地分支和远程分支的链接关系没有创建,用命令git branch --set-upstream-to <branch-name> origin/<branch-name>
。
这就是多人协作的工作模式,一旦熟悉了,就非常简单。
小结
git remote -v
;git push origin branch-name
,如果推送失败,先用git pull
抓取远程的新提交;git checkout -b branch-name origin/branch-name
,本地和远程分支的名称最好一致;git branch --set-upstream branch-name origin/branch-name
;git pull
,如果有冲突,要先处理冲突。git tag <tagname>
用于新建一个标签,默认为HEAD
,也可以指定一个commit id;git tag -a <tagname> -m "blablabla..."
可以指定标签信息;git tag
可以查看所有标签。git push origin <tagname>
可以推送一个本地标签;git push origin --tags
可以推送全部未推送过的本地标签;git tag -d <tagname>
可以删除一个本地标签;git push origin :refs/tags/<tagname>
可以删除一个远程标签。.gitignore
;.gitignore
文件本身要放到版本库里,并且可以对.gitignore
做版本管理!参考文献
Git教程 - 廖雪峰的官方网站
https://www.liaoxuefeng.com/wiki/896043488029600
github-git-cheat-sheet
https://github.github.com/training-kit/downloads/github-git-cheat-sheet.pdf
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!