程序猿的必备神器:Git远程仓库的使用手法详解

作为一个程序猿,如果说你对这个GitHub不了解,那么就很尴尬了!

学会使用这个东东是很有必要的!

至于为什么往下看就是了。

如果看完,你有了想法,就去试着去GitHub注册个账号,然后安装一下,再试着操作一遍!

注:以下命令是在Linux环境下的命令,记得哦,不过也是可以在windows安装好的Git Bash中使用,挺方便的!

Git的诞生

同生活中的许多伟大事件一样,Git 诞生于一个极富纷争大举创新的年代。1991年,Linus创建了开源的Linux,并且有着为数众多的参与者。虽然有世界各地的志愿者为Linux编写代码,但是绝大多数的 Linux 内核维护工作都花在了提交补丁和保存归档的繁琐事务上(1991-2002年间)。在这期间,所有的源代码都是由Linus手工合并。因为Linus坚定地反对CVS和SVN,这些集中式的版本控制系统(集中式和分布式我们会在接下来的内容讲解)不但速度慢,而且必须联网才能使用。虽然有一些商用的版本控制系统,比CVS、SVN好用,但那是付费的,和Linux的开源精神不符。

不过,到了2002 年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是整个项目组启用了一个商业版本的分布式版本控制系统 BitKeeper 来管理和维护代码。BitKeeper的东家BitMover公司出于人道主义精神,授权Linux社区免费使用这个版本控制系统。安定团结的大好局面在2005年被打破,开发BitKeeper 的商业公司同 Linux 内核开源社区的合作关系结束,原因是Linux社区牛人聚集,开发Samba的Andrew试图破解BitKeeper的协议,这么干的其实也不只他一个,但是被BitMover公司发现了,于是BitMover公司收回了Linux社区的免费使用权。这就迫使Linux开源社区( 特别是Linux的缔造者 Linus Torvalds )不得不吸取教训,只有开发一套属于自己的版本控制系统才不至于重蹈覆辙。

他们对新的系统制订了若干目标:速度 、 简单的设计 、 对非线性开发模式的强力支持(允许上千个并行开发的分支)、完全分布式、有能力高效管理类似 Linux 内核一样的超大规模项目(速度和数据量)。自诞生于 2005 年以来,Git 日臻成熟完善,迅速成为最流行的分布式版本控制系统,在高度易用的同时,仍然保留着初期设定的目标。它的速度飞快,极其适合管理大项目,它还有着令人难以置信的非线性分支管理系统,可以应付各种复杂的项目开发需求。2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,包括jQuery,PHP,Ruby等等。

历史就是这么偶然,如果不是当年BitMover公司威胁Linux社区,可能现在我们就没有免费而超级好用的Git了。

Linus一直痛恨的CVS及SVN都是集中式的版本控制系统,而Git是分布式版本控制系统,集中式和分布式版本控制系统有什么区别呢?

先说集中式版本控制系统,版本库是集中存放在中央服务器的,而大家工作的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始工作,工作完成,再把自己的修订推送给中央服务器。这类系统,都有一个单一的集中管理的服务器,保存所有文件的修订版本,而协同工作的人们都通过客户端连到这台服务器,取出最新的文件或者提交更新。

那分布式版本控制系统与集中式版本控制系统有何不同呢?首先,分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。

和集中式版本控制系统相比,分布式版本控制系统的安全性要高很多,因为每个人电脑里都有完整的版本库,某一个人的电脑坏掉了不要紧,随便从其他人那里复制一个就可以了。而集中式版本控制系统的中央服务器要是出了问题,所有人都没法干活了。

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

许多这类系统都可以指定和若干不同的远端代码仓库进行交互。籍此,你就可以在同一个项目中,分别和不同工作小组的人相互协作。你可以根据需要设定不同的协作流程,比如层次模型式的工作流,而这在以前的集中式系统中是无法实现的。

Git的配置

使用Git的第一件事就是设置你的名字和email,这些就是你在提交commit时的签名,每次提交记录里都会包含这些信息。使用git config命令进行配置:

$ git config --global user.name "Scott Chacon"

$ git config --global user.email "schacon@gmail.com"

执行了上面的命令后,会在家目录(/home/shiyanlou)下建立一个叫.gitconfig 的文件(该文件为隐藏文件,需要使用ls -al查看到). 内容一般像下面这样,可以使用vim或cat查看文件内容:

$ cat ~/.gitconfig

[user]

        email = schacon@gmail.com

        name = Scott Chacon

上面的配置文件就是Git全局配置的文件,一般配置方法是git config --global <配置名称> <配置的值>。

如果你想使项目里的某个值与前面的全局设置有区别(例如把私人邮箱地址改为工作邮箱),你可以在项目中使用git config 命令不带 --global 选项来设置. 这会在你当前的项目目录下创建 .git/config,从而使用针对当前项目的配置。

获得一个Git仓库

既然我们现在把一切都设置好了,那么我们需要一个Git仓库。有两种方法可以得到它:一种是从已有的Git仓库中clone (克隆,复制);还有一种是新建一个仓库,把未进行版本控制的文件进行版本控制

Clone一个仓库

为了得到一个项目的拷贝(copy),我们需要知道这个项目仓库的地址(Git URL). Git能在许多协议下使用,所以Git URL可能以ssh://, http(s)://, git://. 有些仓库可以通过不只一种协议来访问。

我们在github.com上提供了一个名字为gitproject的供大家测试的公有仓库,这个仓库可以使用下面方式进行clone:

clone 操作完成后,会发现当前目录下多了一个gitproject文件夹,这个文件夹里的内容就是我们刚刚clone下来的代码。由于当前`gitproject仅是测试项目,里面仅有一个README.md文件。

$ cd gitproject/

(master)$ ls

README.md

细心的同学可以发现在命令提示符$前面多了个(master)。这是由于实验楼的Linux使用的是zsh Shell,zsh会判断当前的目录是否有Git仓库,如果是的话则自动把目前所在的git分支显示在提示符中。Git 分支的概念我们会在稍后介绍。

初始化一个新的仓库

可以对一个已存在的文件夹用下面的命令让它置于Git的版本控制管理之下。

创建代码目录project:

$ cd /home/shiyanlou/

$ mkdir project

进入到代码目录,创建并初始化Git仓库:

$ cd project

$ git init

Git会输出:

Initialized empty Git repository in /home/shiyanlou/project/.git/

通过ls -la命令会发现project目录下会有一个名叫.git 的目录被创建,这意味着一个仓库被初始化了。可以进入到.git目录查看下有哪些内容。

正常的工作流程

git的基本流程如下:

1. 创建或修改文件

2. 使用git add命令添加新创建或修改的文件到本地的缓存区(Index)

3. 使用git commit命令提交到本地代码库

4. (可选,有的时候并没有可以同步的远端代码库)使用git push命令将本地代码库同步到远端代码库

创建和修改文件

进入我们刚才建立的project目录,分别创建文件file1,file2,file3:

$ cd project

$ touch file1 file2 file3

修改文件,可以使用vim编辑内容,也可以直接echo添加测试内容。

$ echo "test" >> file1

$ echo "test" >> file2

$ echo "test" >> file3

此时可以使用git status命令查看当前git仓库的状态:

$ git status

On branch master

Initial commit

Untracked files:

   (use "git add <file>...") to include in what will be committed)

       file1

       file2

       file3

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

可以发现,有三个文件处于untracked状态,下一步我们就需要用git add命令将他们加入到缓存区(Index)。

使用git add加入缓存区

使用git add命令将新建的文件添加到:

$ git add file1 file2 file3

然后再次执行git status就会发现新的变化:

$ git status

On branch master

Initial commit

Changes to be committed:

    (use "git rm --cached <file>..." to unstage)

       new file: file1

       new file: file2

       new file: file3

你现在为commit做好了准备,你可以使用 git diff 命令再加上 --cached 参数,看看缓存区中哪些文件被修改了。进入到git diff --cached界面后需要输入q才可以退出:

$ git diff --cached

如果没有--cached参数,git diff 会显示当前你所有已做的但没有加入到索引里的修改。

如果你要做进一步的修改, 那就继续做, 做完后就把新修改的文件加入到缓存区中。

使用git commit提交修改

当所有新建,修改的文件都被添加到了缓存区,我们就要使用git commit提交到本地仓库:

$ git commit -m "add 3 files"

需要使用-m添加本次修改的注释,完成后就会记录一个新的项目版本。除了用git add 命令,我们还可以用下面的命令将所有没有加到缓存区的修改也一起提交,但-a命令不会添加新建的文件。

$ git commit -a -m "add 3 files"

再次输入git status查看状态,会发现当前的代码库已经没有待提交的文件了,缓存区已经被清空。

至此,我们完成了第一次代码提交,这次提交的代码中我们创建了三个新文件。需要注意的是如果是修改文件,也需要使用git add命令添加到缓存区才可以提交。如果是删除文件,则直接使用git rm命令删除后会自动将已删除文件的信息添加到缓存区,git commit提交后就会将本地仓库中的对应文件删除。

这时如果我们希望将本地仓库关联到远端服务器,我们可以使用 git remote 命令,不同于刚刚的 git clone 命令,直接将远端的仓库克隆下来。 我们当前的仓库是使用 git init 初始化的本地仓库,所以我们需要将本地仓库与远程仓库关联,使用如下命令(需要修改下面的远程仓库地址为自己的仓库地址):

对于上述命令而言,git remote add 命令用于添加远程主机,origin 是主机名,此处我们可以自定义,不一定非要使用 origin,而

是我自己的远程仓库,此处需要替换为自己的远程仓库地址

这个时候如果本地的仓库连接到了远程Git服务器,可以使用下面的命令将本地仓库同步到远端服务器:

# 需要输入仓库对应的用户名和密码

$ git push origin master

分支与合并

Git 的分支可以让你在主线(master分支)之外进行代码提交,同时又不会影响代码库主线。分支的作用体现在多人协作开发中,比如一个团队开发软件,你负责独立的一个功能需要一个月的时间来完成,你就可以创建一个分支,只把该功能的代码提交到这个分支,而其他同事仍然可以继续使用主线开发,你每天的提交不会对他们造成任何影响。当你完成功能后,测试通过再把你的功能分支合并到主线。

创建分支

一个Git仓库可以维护很多开发分支。现在我们来创建一个新的叫 experimental的分支:

$ git branch experimental

运行git branch命令可以查看当前的分支列表,以及目前的开发环境处在哪个分支上:

$ git branch

 experimental

* master

切换分支

experimental 分支是你刚才创建的,master分支是Git系统默认创建的主分支。星号标识了你当工作在哪个分支下,输入git checkout 分支名可以切换到其他分支:

$ git checkout experimental

Switched to branch 'experimental'

切换到experimental分支,切换完成后,先编辑里面的一个文件,再提交(commit)改动,最后切换回 “master”分支:

# 修改文件file1

$ echo "update" >> file1

# 查看当前状态

$ git status

# 添加并提交file1的修改

$ git add file1

$ git commit -m "update file1"

# 查看file1的内容

$ cat file1

test

update

# 切换到master分支

$ git checkout master

查看下file1中的内容会发现刚才做的修改已经看不到了。因为刚才的修改时在experimental分支下,现在切换回了master分支,目录下的文件都是master分支上的文件了。

合并分支

现在可以在master分支下再作一些不同的修改:

# 修改文件file2

$ echo "update again" >> file2

# 查看当前状态

$ git status

# 添加并提交file2的修改

$ git add file2

$ git commit -m "update file2 on master"

# 查看file2的内容

$ cat file2

test

update again

这时,两个分支就有了各自不同的修改,分支的内容都已经不同,如何将多个分支进行合并呢?

可以通过下面的git merge命令来合并experimental到主线分支master:

# 切换到master分支

$ git checkout master

# 将experimental分支合并到master

$ git merge -m 'merge experimental branch' experimental

-m参数仍然是需要填写合并的注释信息。

由于两个 branch 修改了两个不同的文件,所以合并时不会有冲突,执行上面的命令后合并就完成了。

如果有冲突,比如两个分支都改了一个文件 file3,则合并时会失败。首先我们在master分支上修改file3文件并提交:

# 切换到master分支

$ git checkout master

# 修改file3文件

$ echo "master: update file3" >> file3

# 提交到master分支

$ git commit -a -m 'update file3 on master'

然后切换到experimental,修改file3并提交:

# 切换到experimental分支

$ git checkout experimental

# 修改file3文件

$ echo "experimental: update file3" >> file3

# 提交到experimental分支

$ git commit -a -m 'update file3 on experimental'

切换到master进行合并:

$ git checkout master

$ git merge experimental

Auto-merging file3

CONFLICT (content): Merge conflict in file3

Automatic merge failed; fix conflicts and then commit the result.

合并失败后先用git status查看状态,会发现file3显示为both modified,查看file3内容会发现:

$ cat file3

test

<<<<<<< HEAD

master: update file3

=======

experimental: update file3

>>>>>>> experimental

上面的内容也可以使用git diff查看,先前已经提到git diff不加参数可以显示未提交到缓存区中的修改内容。

可以看到冲突的内容都被添加到了file3中,我们使用vim编辑这个文件,去掉git自动产生标志冲突的<<<<<<等符号后,根据需要只保留我们需要的内容后保存,然后使用git add file3和git commit命令来提交合并后的file3内容,这个过程是手动解决冲突的流程。

# 编辑冲突文件

$ vim file3

# 提交修改后的文件

$ git add file3

$ git commit -m 'merge file3'

删除分支

当我们完成合并后,不再需要experimental时,可以使用下面的命令删除:

$ git branch -d experimental

git branch -d只能删除那些已经被当前分支的合并的分支. 如果你要强制删除某个分支的话就用git branch –D

撤销一个合并

如果你觉得你合并后的状态是一团乱麻,想把当前的修改都放弃,你可以用下面的命令回到合并之前的状态:

$ git reset --hard HEAD^

# 查看file3的内容,已经恢复到合并前的master上的文件内容

$ cat file3

查看日志

git log命令可以显示所有的提交(commit):

$ git log

如果提交的历史纪录很长,回车会逐步显示,输入q可以退出。

git log有很多选项,可以使用git help log查看,例如下面的命令就是找出所有从"v2.5“开始在 fs 目录下的所有 Makefile 的修改(这个只是举例,不用操作):

$ git log v2.5.. Makefile fs/

Git会根据git log命令的参数,按时间顺序显示相关的提交(commit)。

日志统计

git log命令可以显示所有的提交(commit):

$ git log

如果提交的历史纪录很长,回车会逐步显示,输入q可以退出。

git log有很多选项,可以使用git help log查看,例如下面的命令就是找出所有从"v2.5“开始在 fs 目录下的所有 Makefile 的修改(这个只是举例,不用操作):

$ git log v2.5.. Makefile fs/

Git会根据git log命令的参数,按时间顺序显示相关的提交(commit)。

格式化日志

你可以按你的要求来格式化日志输出。--pretty 参数可以使用若干表现格式,如oneline:

$ git log --pretty=oneline

或者你也可以使用 short 格式:

$ git log --pretty=short

你也可用medium,full,fuller,email 或raw。 如果这些格式不完全符合你的需求, 你也可以用--pretty=format参数定义格式。

--graph 选项可以可视化你的提交图(commit graph),会用ASCII字符来画出一个很漂亮的提交历史(commit history)线:

$ git log --graph --pretty=oneline

日志排序

日志记录可以按不同的顺序来显示。如果你要指定一个特定的顺序,可以为git log命令添加顺序参数。

按默认情况,提交会按逆时间顺序显示,可以指定--topo-order参数,让提交按拓扑顺序来显示(就是子提交在它们的父提交前显示):

$ git log --pretty=format:'%h : %s' --topo-order --graph

你也可以用 --reverse参数来逆向显示所有提交日志。

总结命令

本节讲解了几个基本命令:

· git config:配置相关信息

· git clone:复制仓库

· git init:初始化仓库

· git add:添加更新内容到索引中

· git diff:比较内容

· git status:获取当前项目状况

· git commit:提交

· git branch:分支相关

· git checkout:切换分支

· git merge:合并分支

· git reset:恢复版本

· git log:查看日志

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容

  • 初始化git 配置git 使用Git的第一件事就是设置你的名字和email,这些就是你在提交commit时的签名,...
    MiracleJQ阅读 1,380评论 0 0
  • Git 基础 基本原理 客户端并不是只提取最新版本的文件快照,而是把代码仓库完整的镜像下来。这样一来,任何一处协同...
    __silhouette阅读 15,847评论 5 147
  • Git 命令行学习笔记 Git 基础 基本原理 客户端并不是只提取最新版本的文件快照,而是把代码仓库完整的镜像下来...
    sunnyghx阅读 3,897评论 0 11
  • 1.git的安装 1.1 在Windows上安装Git msysgit是Windows版的Git,从https:/...
    落魂灬阅读 12,639评论 4 54
  • 由南门变北门,由农村到县城,由高级到中级,……由白衣二中升级到芦花实验中学。 时光飞逝,转瞬二十年,好像就在昨天。...
    放飞心情_ac90阅读 373评论 0 0