git的使用与设计思想

cover

生活中常常有这样的场景,你写一个文档,想退回以前的某个状态,但发现没有以前的存档。或者很多人协作做一个东西(比如和你的对象一起写小说),但发现大家各自做的东西总是有冲突。遇到这样的情况怎么办呢(恐慌脸),别怕,今天我给大家深入浅出的介绍一下git的基本的使用技巧。

首先,git是一个分布式版本控制系统。分布式版本控制,意味着版本库分布在每一个人的电脑上,这样你修改完后能直接提交到本地版本库,如果别人要得到你的修改从你那复制一份就好了。当然,一般我们会拿一台中央服务器用来交换大家的修改。

给大家介绍一下安装git的方法,这里是安装git的方法

好的,我没有偷懒。

大家现在在命令行里输入git,按回车,先看一下它的输出,上面包括的最基本的用法简介。
初次使用git,需要设置你的邮箱和名字,比如:

$ git config --global user.name "Tian Flower Flower"
$ git config --global user.email flower@example.com

接着给大家介绍一下怎么使用这项强大的工具和你的小伙伴一起敲代码。

首先建立一个空文件夹,打开终端(windows用户搜索cmd),进入那个文件夹下,然后输入git init,这时候那个文件夹就被git初始化了。还有一种初始化的方式,假如对方已经写了一部分代码,你可以直接git clone 下来他的仓库地址。被git初始化后,文件夹就会出现一个新的隐藏文件夹.git,于一个 Git 仓库来说,其 .git 目录保存了整个 Git 项目的所有数据与资源。

现在你的目录下有三个文件(它们已经在本地仓库里了),sing.py,dance.py,read.py,然后你对它们每个文件都加了一行代码。那么问题来了,你想提交到本地仓库的时候附加上提交的备注,"修改了音乐的部分"和"修改了阅读的部分",你需要先提交sing.py、dance.py,再提交read.py。同时为了便于管理这些文件,git还会对这些文件建立状态文件(你输入git status就能看到状态,输入git status --help可以查看具体的参数,其它的命令也是后面加个--help)。因为git一般是在命令行里使用的,所以为了便于添加文件,记录文件状态,git有了暂存区的概念,你可以通过git add sing.py dance.py将文件添加到暂存区,这个时候输入git status,会发现:

~/gitPresentation  master ✗                                                                                                                                                              ✚ ◒  
▶ git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

    new file:   dance.py
    new file:   sing.py

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

    read.py

由上面的信息可以看到dance.py和sing.py已经被加入到了暂存区,changes to be commited就是告诉你这些变化待提交,(use "git rm --cached <file>..." to unstage)是告诉你可以用那个命令把文件从暂存区里弄出去。下半部分就是没有在暂存区的。

然后git commit -m "your message"就可以提交到本地仓库了。read.py的操作也是git add 然后 git commit。

这个时候我们查看一下.git/objects

~/gitPresentation  master ✔                                                                                                                                                               0m  
▶ find .git/objects -type f
.git/objects/fe/80e07a67b964e66cf2ac5abb611c3e4b351b33
.git/objects/d3/c9a190f400e0f4e5837c25be288540945e1492
.git/objects/b4/43902473907ac4832f821db909f98964ee9f3e
.git/objects/9d/9991b2ac7598604dad272072a4979fb48abddc
.git/objects/f0/2275089261d075a1b33ddb281c310d2365cb04
.git/objects/60/59d3d2e913d238833e9cf2707b5379794fafb3
.git/objects/7d/a981ddf41583e61b41385ca86c7ba5953bc545

可以看到这里有了很多对象,那这个时候我们给read.py增加一个空行,提交后再输入一下这个命令:

~/gitPresentation  master ✔                                                                                                                                                               0m  
▶ find .git/objects -type f                             
.git/objects/fe/80e07a67b964e66cf2ac5abb611c3e4b351b33
.git/objects/36/f4d833fae786bf32082e289808bc8988c039d2
.git/objects/d3/c9a190f400e0f4e5837c25be288540945e1492
.git/objects/6d/fbda7939f771046777e8858bc4d742b4be5e2c
.git/objects/b4/43902473907ac4832f821db909f98964ee9f3e
.git/objects/9d/9991b2ac7598604dad272072a4979fb48abddc
.git/objects/f0/2275089261d075a1b33ddb281c310d2365cb04
.git/objects/60/59d3d2e913d238833e9cf2707b5379794fafb3
.git/objects/7d/a981ddf41583e61b41385ca86c7ba5953bc545
.git/objects/7d/9a8143b3d66a8cb5178f7b780015bcfdaa46ea

可以发现对象变多了。
你每次修改文件提交后git都会把修改后的文件完整的存储起来。你可能想git为什么不每次记录修改的地方,按前面那种方法太浪费空间了。其实是可以的,git默认使用松散对象来存储文件,当太多空间被浪费,或者推送到远程服务器的时候,git会调用git gc,来将松散对象打包好,来节省空间,在打包好的packfile中,git只存储变化的部分,然后用一个指针指向之前的文件。

我们可以手动调用git gc来试一下:

~/gitPresentation  master ✔                                                                                                                                                              16m  
▶ git count-objects -v                                  
count: 10
size: 40
in-pack: 0
packs: 0
size-pack: 0
prune-packable: 0
garbage: 0
size-garbage: 0

~/gitPresentation  master ✔                                                                                                                                                              16m  
▶ git gc
Counting objects: 10, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (10/10), done.
Writing objects: 100% (10/10), done.
Total 10 (delta 0), reused 0 (delta 0)

~/gitPresentation  master ✔                                                                                                                                                              16m  
▶ git count-objects -v
count: 0
size: 0
in-pack: 10
packs: 1
size-pack: 2
prune-packable: 0
garbage: 0
size-garbage: 0

~/gitPresentation  master ✔                                                                                                                                                              16m  
▶ find .git/objects -type f
.git/objects/pack/pack-2c2c342dc3d81f01aa69d2bd2eedf5d4429264d9.pack
.git/objects/pack/pack-2c2c342dc3d81f01aa69d2bd2eedf5d4429264d9.idx
.git/objects/info/packs

~/gitPresentation  master ✔                                                                                                                                                              16m  
▶ ls
dance.py  read.py  sing.py

可以看到之前那十个松散对象都被打包好了。

现在你想写有关巴赫的代码,你的朋友想写有关莫扎特的代码,于是为了避免冲突,你创建了一个叫巴赫的分支,你的朋友创建了一个叫莫扎特的分支。(这里提醒一下,git pull默认只获取远程的master分支,如果要checkout到远程其它的分支,首先要git branch -r,然后checkout到对应的分支。)

现在你先checkout到Bach分支,进行魔改操作,然后提交:

~/gitPresentation  master ✔                                                                                                                                                              22m  
▶ git checkout Bach
Switched to branch 'Bach'

~/gitPresentation  Bach ✔                                                                                                                                                                29m  
▶ ls
dance.py  read.py  sing.py

~/gitPresentation  Bach ✔                                                                                                                                                                29m  
▶ vim note.py 

~/gitPresentation  Bach ✗                                                                                                                                                              31m ◒  
▶ git add note.py 

~/gitPresentation  Bach ✗                                                                                                                                                              31m ✚  
▶ git commit -m "note"
[Bach 4f38850] note
 1 file changed, 5 insertions(+)
 create mode 100644 note.py

~/gitPresentation  Bach ✔                                                                                                                                                                 0m  
▶ git log --oneline
4f38850 (HEAD -> Bach) note
36f4d83 (master, Mozart) add a empty line
b443902 read.py
7da981d music

你先把Bach分支合并到master分支:

~/gitPresentation  master ✔                                                                                                                                                              37m  
▶ git merge Bach
Updating 36f4d83..4f38850
Fast-forward
 note.py | 5 +++++
 1 file changed, 5 insertions(+)
 create mode 100644 note.py
~/gitPresentation  master ✔                                                                                                                                                               9m  
▶ git log --oneline
4f38850 (HEAD -> master, Bach) note
36f4d83 add a empty line
b443902 read.py
7da981d music

你的朋友在Mozart分支下也创建了一个note.py。然后你想把Mozart分支也合并到master分支,那么问题来了,Mozart分支下也有note.py,内容差不多,和master分支下的note.py冲突了,我们可以git diff一下:

~/gitPresentation  master ✔                                                                                                                                                              11m  
▶ git diff master Mozart 
diff --git a/note.py b/note.py
index ce070d4..0c85471 100644
--- a/note.py
+++ b/note.py
@@ -1,5 +1,5 @@
 def note():
-    print('note')
+    print('Mozart')
 
 if __name__ == '__main__':
     note()

可以看出来有不同的地方,我们需要手动处理冲突。
这里讲一下git merge是如何判断冲突的,贴一段官方文档里的话:

For conflicting paths, the index file records up to three versions: stage 1 stores the version from the common ancestor, stage 2 from HEAD, and stage 3 from MERGE_HEAD (you can inspect the stages with git ls-files -u). The working tree files contain the result of the "merge" program; i.e. 3-way merge results with familiar conflict markers <<< === >>>.

就是说两个分支合并,先和公共的基点做对比,不然,要是一个分支比另一个分支多一个文件,你怎么知道是a分支增加了一个文件,还是b分支删除了一个文件。

手动处理冲突后,我们进行合并,然后查看提交历史:

~/gitPresentation  master ✔                                                                                                                                                              25m  
▶ git merge Mozart 
Merge made by the 'recursive' strategy.

~/gitPresentation  master ✔                                                                                                                                                               0m  
▶ git log --graph --oneline
*   0cfd35e (HEAD -> master) Merge branch 'Mozart'
|\  
| * cf331f2 (Mozart) solve
| * 756753d Mozart not
* | 4f38850 (Bach) note
|/  
* 36f4d83 add a empty line
* b443902 read.py
* 7da981d music

可以看到现在Bach分支和Mozart分支都已经合并到了master分支,此时要记住最好删除Bach分支和Mozart分支,避免历史混乱。

git还有一种合并方法叫rebase,它的原理是将另一条分支上面提交的commit在master上重演一遍,但是因为rebase会改写历史记录,所以不要在公共分支上用rebase,不然可能一不小心,你的朋友们都会仇恨你。不过这里提一个有用的rebase命令,如果你想修改上一个commit信息,自然是用git commit --amend,但是修改很久之前的呢,可以用git rebase -i(查看git rebase --help的INTERACTIVE MODE)。

好,git今天就简单的讲到这了,谢谢大家。

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

推荐阅读更多精彩内容

  • git作为时下最流行的代码管理工具,Git权威指南总结了十条喜欢Git的理由: 异地协同工作; 现场版本控制; 重...
    古斟布衣阅读 1,826评论 0 12
  • 1.设置 初次使用需要设置姓名和邮箱git config --global user.name "git用户名"g...
    jrg陈咪咪sunny阅读 758评论 0 1
  • 1.git的安装 1.1 在Windows上安装Git msysgit是Windows版的Git,从https:/...
    落魂灬阅读 12,665评论 4 54
  • 1. 冬天的早上,寒风瑟瑟,天刚蒙蒙亮,我依然6点半下楼等班车。 每天早上一位环卫阿姨都带着她那条长得很高大的狗在...
    北方的橙子阅读 518评论 2 3
  • flex基于水平和垂直的两条基准线进行布局。 理解了这一点剩下的看文档就好了~ 水平轴 默认的flex布局是按水平...
    云峰yf阅读 898评论 0 0