Git的基本用法

Git的配置

在使用Git之前需要设置用户名和用户email。这些是提交代码的签名,每次的提交记录例都会包含这些信息。使用git config命令进行配置:

$ git config --global user.name "clldaxigua"
$ git config --global user.email "clldaxigua@126.com"

在执行了上面的命令以后,会在用户目录下(~/)生成一个.gitconfig文件。该文件就是Git全局的配置文件,内容如下:

[user]                                                                                                                                                                              
    name = clldaxigua
    email = clldaxigua@126.com

Git的一般配置方法是git config --global <配置名称> <配置的值>。如果想是项目里的某个值与全局配置有区别,可以在项目中使用不带—global选项的git config命令来设置。此时就会在当前的项目目录下创建.git/config,该配置文件仅对该项目有效。

获得一个Git仓库

在设置好Git的配置以后,就需要一个Git仓库。有两种方法可以获得Git仓库:一种是从已有的Git仓库中clone;还有一种是新建一个仓库,实现对项目文件的版本控制。

Clone一个仓库

为了获得一个项目的拷贝,我们需要知道这个项目仓库的地址(Git URL)。Git支持多种通讯协议,包括ssh, http, git等。
实验楼提供了一个测试用的共有仓库,可以使用下面的方法进行克隆:

$ git clone http://git.shiyanlou.com/shiyanlou/gitproject

Clone操作完成后,当前目录下多出一个gitproject目录,这个目录中的内容就是git clone获得到的。由于gitproject仅是测试项目,里面只有一个README.md文件。

初始化一个新的仓库

可以对一个已存在的目录用下面的命令对该目录进行版本控制。

$ cd ~
$ mkdir project
$ cd project
$ git init
Initialized empty Git repository in /home/chen/project/.git/

.git目录的内容可以参考《Git Community Book中文版》

'Git目录'是为你的项目存储所有历史和元信息的目录,包括所有的对(commits, trees, blobs, tags),这些对象指向不同的分支。
每一个项目只能有一个'Git目录'(这和SVN,CVS的每个子目录中都有此类目录相反), 这个叫'.git'的目录在你项目的根目录下(这是默认设置,但并不是必须的). 如果你查看这个目录的内容, 你可以看所有的重要文件:

$ tree -L 1
.
|-- HEAD # 这个git项目当前处在哪个分支里
|-- config # 项目的配置信息,git config命令会改动它
|-- description # 项目的描述信息
|-- hooks/ # 系统默认钩子脚本目录
|-- index # 索引文件
|-- logs/ # 各个refs的历史信息
|-- objects/ # Git本地仓库的所有对象 (commits, trees, blobs, tags)
|-- refs/ # 标识你项目里的每个分支指向了哪个提交(commit)

正常的工作流程

Git的基本流程如下:

  • 创建或者修改文件。
  • 使用git add命令添加新建或者修改的文件到本地的缓存区(Index)。
  • 使用git commit命令提交到本地代码库。
  • 使用git push命令将本地代码库同步到远端代码库(可选)。

一个示例

进入project目录,分别创建3个文件file1, file2, file3,并为3个文件添加内容:

$ cd project
$ touch file1 file2 file3
$ echo "test content file1" >> file1
$ echo "test content file2" >> file2
$ echo "test content file3" >> 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)

此时有3个文件处于untracked状态,下一步需要用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 onstage)

     new file:   file1
     new file:   file2
     new file:   file3

此时可以使用git diff --cached命令查看缓存区中哪些文件被修改,如下所示:

$ echo "append" >> file1
$ git diff --cached
diff --git a/file1 b/file1
new file mode 100644
index 0000000..61a4d74
--- /dev/null
+++ b/file1
@@ -0,0 +1 @@
+test content file1
diff --git a/file2 b/file2
new file mode 100644
index 0000000..4367933
--- /dev/null
+++ b/file2
@@ -0,0 +1 @@
+test content file2
diff --git a/file3 b/file3
new file mode 100644
index 0000000..6cd7bad
--- /dev/null
+++ b/file3
@@ -0,0 +1 @@
+test content file3

如果没有—cached参数,则会显示当先所有已做但是没有加入到缓存区里的修改。

$ git diff
diff --git a/file1 b/file1
index 61a4d74..2260863 100644
--- a/file1
+++ b/file1
@@ -1 +1,2 @@
test content file1
+append

在这里需要特别说明的是git diff命令只会显示不在缓存区中的修改,而不会显示不在缓存区的新建文件。也就是说,如果在project文件下新建一个file4,执行git diff命令并不会显示file4。
此时,可以通过commit命令将缓存区中的代码提交到本地代码仓库中:

$ git commit -m "add 3 files"
[master (root-commit) b148ad6] add 3 files
 3 files changed, 3 insertions(+)
 create mode 100644 file1
 create mode 100644 file2
 create mode 100644 file3

再次输入git status查看状态,会发现当前的缓存区中已经没有待提交的文件。至此,第一次代码提交已经完成。之后如果需要添加或者修改文件,则需要将添加或者修改的文件git add到缓存区中才可以提交。如果是删除文件,则使用git rm命令删除后会自动将已删除文件添加到缓存区,此时执行git commit命令后就会将仓库中的对应文件删除。
这个时候,如果本地的仓库连接到远程的Git服务器,则可以使用下面的命令将本地仓库同步到远端服务器:

$ git push origin master

分支与合并

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

分支

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

$ git branch experimental

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

$ git branch
   experimental
 * master

experimental 分支是刚才创建的分支,master分支是Git系统默认创建的主分支。星号标识当前的工作分支。输入git checkout [branch name]可以切换到其他分支:

$ git checkout experimental
Switched to branch 'experimental'

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

# 修改文件file1
$ echo "update" >> file1
# 添加并提交file1的修改
$ git add file1
# 提交代码
$ git commit -m "update file1"
# 查看experimental分支中file1的内容
$ cat file1
test
update
# 切换到master分支
$ git checkout master
# 查看master分支中file1的内容
$ cat file1
test

此时查看file1中的内容会发现,刚才做的修改已经消失。因为刚才的修改时在experimental分支下,现在切换回了master分支,目录下的文件都是master分支上的文件了。现在可以在master分支下再作一些不同的修改:

# 修改文件file2
$ echo "update" >> file2
# 添加并提交file2的修改
$ git add file2
$ git commit -m "update file2"
# 查看file2的内容
$ cat file2
test
update again

合并

这时,两个分支就有了各自不同的修改,分支的内容都已经不同。可以通过git merge命令来合并experimental到主线分支master:

# 切换到master分支
$ git checkout master
# 将experimental分支合并到master
$ git merge -m 'merge experimental branch' experimental

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

合并冲突

如果有冲突,比如两个分支修改同一个文件,则合并时会失败。首先在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
# 提交到master分支
$ 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不加参数可以显示未提交到缓存区中的修改内容。

$ git diff
diff --cc file3
index 9e160c6,1b26a67..0000000
--- a/file3
+++ b/file3
@@@ -1,2 -1,2 +1,6 @@@
  test3
++<<<<<<< HEAD
 +master: update
++=======
+ experimental: update
++>>>>>>> experimental

同时,冲突的内容都被添加到了file3中。

 $ cat file3
test3
<<<<<<< HEAD
master: update
=======
experimental: update
>>>>>>> experimental

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

删除分支

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

$ git branch -d experimental

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

撤销一个合并

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

$ git reset --hard HEAD^

快速向前合并

还有一种需要特殊对待的情况,在前面没有提到。通常,一个合并会产生一个合并提交(commit), 把两个父分支里的每一行内容都合并进来。
但是,如果当前的分支和另一个分支没有内容上的差异,就是说当前分支的每一个提交(commit)都已经存在另一个分支里了,git 就会执行一个“快速向前"(fast forward)操作;git 不创建任何新的提交(commit),只是将当前分支指向合并进来的分支。

Git日志

查看日志

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

$ git log

日志统计

如果用--stat选项使用'git log',它会显示在每个提交(commit)中哪些文件被修改了, 这些文件分别添加或删除了多少行内容,这个命令相当于打印详细的提交记录:

$ git log --stat

格式化日志

你可以按你的要求来格式化日志输出。--pretty 参数可以使用若干表现格式。格式化输出的格式支持oneline, short, medium, full, fuller, email 或raw。 此外,也可以用--pretty=format参数定义格式。
--graph 选项可以可视化提交图(commit graph),利用ASCII字符画出一个提交历史(commit history)线:

$ git log --graph --pretty=oneline

日志排序

日志记录可以按不同的顺序来显示。如果需要指定一个特定的顺序,可以为git log命令添加顺序参数。
按默认情况,提交会按逆时间顺序显示,可以指定--topo-order参数,让提交按拓扑顺序来显示(就是子提交在它们的父提交前显示);也可以用 --reverse参数来逆向显示所有提交日志。

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

推荐阅读更多精彩内容

  • Git是目前最流行的版本管理系统,也是最先进的分布式版本控制系统(distributed version cont...
    pro648阅读 5,678评论 1 17
  • 1.git的安装 1.1 在Windows上安装Git msysgit是Windows版的Git,从https:/...
    落魂灬阅读 12,649评论 4 54
  • 简介 首先我认为它是开发者常用的一个操作系统。通过在cmd上输入一些指令来实现开发人员想要实现的目的。 git的一...
    markdown小天后阅读 244评论 1 0
  • git常用命令 GIT常用命令备忘:http://stormzhang.com/git/2014/01/27/gi...
    新篇章阅读 8,456评论 1 26
  • 一夕之间, 季节转换了冷暖。 心事还在盛夏的夜里辗转, 眼前已然是一派初秋的清寒。 伸手触摸一瓣落花飘飞的思念, ...
    晴云秋月AL阅读 250评论 0 2