Git教程

1. Windows上安装Git

  在Windows上使用Git,可以从Git官网直接下载安装程序,(网速慢的同学请移步国内镜像),然后按默认选项安装即可。
  安装完成后,在开始菜单里找到“Git”->“Git Bash”,蹦出一个类似命令行窗口的东西,就说明Git安装成功!
  安装完成后,还需要最后一步设置,在命令行输入:

$ git config --global user.name "Your Name"
$ git config --global user.email "Your Email"

2.创建版本库

2.1 将一个目录(可以非空)作为该仓库目录

$ mkdir learngit
$ cd learngit

注:为了避免遇到莫名其妙的问题,目录名和文件名最好不要包含中文

2.2 通过git init命令把这个目录变成Git可以管理的仓库:

$ git init
Initialized empty Git repository in E:/git/learnGit/.git/

  当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的,没事千万不要手动修改这个目录里面的文件,不然改乱了,就把Git仓库给破坏了。

2.3 将文件添加到版本库

  • 说明:
      所有的版本控制系统,其实只能跟踪文本文件的改动,比如TXT文件,网页,所有的程序代码等等,Git也不例外。版本控制系统可以告诉你每次的改动,比如在第5行加了一个单词“Linux”,在第8行删了一个单词“Windows”。而图片、视频这些二进制文件,虽然也能由版本控制系统管理,但没法跟踪文件的变化,只能把二进制文件每次改动串起来,也就是只知道图片从100KB改成了120KB,但到底改了啥,版本控制系统不知道,也没法知道。
      千万不要使用Windows自带的记事本编辑任何文本文件。原因是Microsoft开发记事本的团队使用了一个非常弱智的行为来保存UTF-8编码的文件,他们自作聪明地在每个文件开头添加了0xefbbbf(十六进制)的字符,你会遇到很多不可思议的问题,比如,网页第一行可能会显示一个“?”,明明正确的程序一编译就报语法错误,等等,都是由记事本的弱智行为带来的。建议你下载Notepad++代替记事本,不但功能强大,而且免费!记得把Notepad++的默认编码设置为UTF-8 without BOM即可。

  • 添加步骤:

  • 创建一个readme.txt,内容如下:

         write a readme.txt
    
  • 用git add命令添加到仓库

         $ git add readme.txt
    
  • 用git commit命令提交到仓库

         $ git commit -m "wrote a readme.txt file"
         [master (root-commit) dce98bd] wrote a readme.txt file
          1 file changed, 1 insertion(+)
          create mode 100644 readme.txt
    

3. 时光机穿梭

修改readme.txt为:

    write a readme.txt
    change 1

运行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

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

如果能看看具体修改了什么内容,使用git diff:

$ git diff readme.txt
diff --git a/readme.txt b/readme.txt
index 79589fa..2319020 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1 +1,2 @@
 write a readme.txt
+change 1

使用git add命令添加到仓库:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   readme.txt

使用git commit提交到仓库:

$ git commit -m 'change1'
[master 4cb3c0f] change1
 1 file changed, 1 insertion(+)

再用git status查看仓库状态:

$ git status
On branch master
nothing to commit, working tree clean

3.1.版本回退

  再进行一次修改用于测试版本回退,当前readme.txt中的内容为:

write a readme.txt
change 1
change 2

  git log命令显示从最近到最远的提交日志:

$ git log
commit cb0e5027fbd8a470bfcba948fa5c3207b096a27b (HEAD -> master)
Author: GuoYuebo <2698895442@qq.com>
Date:   Sat Jan 20 18:11:29 2018 +0800

    change 2

commit 4cb3c0f255c88be164056f83cf5d6c87957924f9
Author: GuoYuebo <2698895442@qq.com>
Date:   Sat Jan 20 17:33:08 2018 +0800

    change1

commit dce98bd01d5cd1847dcebbcb231aff2b54155d44
Author: GuoYuebo <2698895442@qq.com>
Date:   Sat Jan 20 17:21:22 2018 +0800

    wrote a readme.txt file

  如果嫌输出信息太多,看得眼花缭乱的,可以试试加上--pretty=oneline参数:

$ git log --pretty=oneline
cb0e5027fbd8a470bfcba948fa5c3207b096a27b (HEAD -> master) change 2
4cb3c0f255c88be164056f83cf5d6c87957924f9 change1
dce98bd01d5cd1847dcebbcb231aff2b54155d44 wrote a readme.txt file

开始回退:
  首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,上一个版本就是HEAD,上上一个版本就是HEAD,当然往上100个版本写100个比较容易数不过来,所以写成HEAD~100。HEAD只是指向某个版本的指针。
  回退使用git reset命令。--hard命令后面再解释:

$ git reset --hard HEAD^
HEAD is now at 4cb3c0f change1
$ git log --pretty=oneline
4cb3c0f255c88be164056f83cf5d6c87957924f9 (HEAD -> master) change1
dce98bd01d5cd1847dcebbcb231aff2b54155d44 wrote a readme.txt file
$ cat readme.txt
write a readme.txt
change 1

  要想从过去回到未来可以通过上面commit id的记录:

$ git reset --hard cb0e5027fbd8a470bfcba948fa5c3207b096a27b
HEAD is now at cb0e502 change 2
$ cat readme.txt
write a readme.txt
change 1
change 2

  若没有记录以前版本的commit id,可以通过git reflog显示之前的提交记录

$ git reflog
cb0e502 (HEAD -> master) HEAD@{0}: reset: moving to cb0e5027fbd8a470bfcba948fa5c3207b096a27b
4cb3c0f HEAD@{1}: reset: moving to HEAD^
cb0e502 (HEAD -> master) HEAD@{2}: commit: change 2
4cb3c0f HEAD@{3}: commit: change1
dce98bd HEAD@{4}: commit (initial): wrote a readme.txt file

  可以通过git reset和其中的commit id回到未来

$ git reset --hard cb0e502
HEAD is now at cb0e502 change 2

3.2.工作区和暂存区

  • 工作区
      就是你在电脑里能看到的目录,比如我的learngit文件夹就是一个工作区
  • 版本库和暂存区
      工作区有一个隐藏目录.git,这个不算工作区,而是Git的版本库。Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区,还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。
  • 提交过程
      第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;
      第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。


    _3_2_1.png

3.3.管理修改

  git管理的是修改,从以下现象可以看出。
  操作步骤:第一次修改 -> git add -> 第二次修改 -> git commit。这样只会提交第一次修改的内容。可以使用git diff HEAD -- readme.txt查看已提交和第二次修改的区别(后一个相对前一个)。

$ git diff HEAD -- readme.txt
diff --git a/readme.txt b/readme.txt
index 82e1ccc..1f087a5 100644
--- a/readme.txt
+++ b/readme.txt
@@ -1,4 +1,4 @@
 write a readme.txt
 change 1
 change 2
-change 3
+change 4

3.4. 撤销修改

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file。该命令使工作区的文件回到最近一次git add或git commit时的版本。

场景2:当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令git reset HEAD file,就回到了场景1,第二步按场景1操作。

场景3:已经提交了不合适的修改到版本库时,想要撤销本次提交,参考版本回退一节,不过前提是没有推送到远程库。

3.5. 删除文件

先在本地删除文件,再使用命令git rm删掉,并且git commit
若错删,则使用git checkout -- file恢复

4. 远程仓库

  1. 创建SSH Key
      在用户主目录下,看看有没有.ssh目录,如果有,再看看这个目录下有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可直接跳到下一步。如果没有,打开Shell(Windows下打开Git Bash),创建SSH Key:

     $ ssh-keygen -t rsa -C "youremail@example.com"
    

  你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。
  如果一切顺利的话,可以在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

  1. 将密钥添加到GitHub账户中
      登陆GitHub,打开“Account settings”,“SSH Keys”页面,然后,点“New SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容。

4.1.添加远程库

  • 首先,登陆GitHub,然后,在右上角找到“Create a new repo”按钮,创建一个新的仓库。
  • 在Repository name填入learngit,其他保持默认设置,点击“Create repository” 按钮,就成功地创建了一个新的Git仓库。
  • 使用命令 git remote add origin git@server-name:userName/repo-name.git关联一个远程库,其中origin为远程库的名称
  • 关联后,使用命令git push -u origin master第一次推送master分支的所有内容;
  • 加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
  • 当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告,输入yes即可
  • 此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改;

4.2. 从远程库克隆

    $ git clone git@github.com:GuoYuebo/learnGit.git

5. 分支管理

5.1 创建与合并分支

  在版本回退里,你已经知道,每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向master,master才是指向提交的,所以,HEAD指向的就是当前分支。
  一开始的时候,master分支是一条线,Git用master指向最新的提交,再用HEAD指向master,就能确定当前分支,以及当前分支的提交点.
  每次提交,master分支都会向前移动一步,这样,随着你不断提交,master分支的线也越来越长:


_5_1_2.png

  当我们创建新的分支,例如dev时,Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,就表示当前分支在dev上:


_5_1_2.png

  假如我们在dev上的工作完成了,就可以把dev合并到master上。Git怎么合并呢?最简单的方法,就是直接把master指向dev的当前提交,就完成了合并:


_5_1_3.png

  所以Git合并分支也很快!就改改指针,工作区内容也不变!合并完分支后,甚至可以删除dev分支。删除dev分支就是把dev指针给删掉,删掉后,我们就剩下了一条master分支:


_5_1_4.png

下面开始实战:

  • 首先,我们创建dev分支,然后切换到dev分支:
$ git checkout -b dev
Switched to a new branch 'dev'
  • git checkout命令加上-b参数表示创建并切换,相当于以下两条命令:
$ git branch dev
$ git checkout dev
Switched to branch 'dev'
  • 用git branch命令查看当前分支,git branch命令会列出所有分支,当前分支前面会标一个*号:
$ git branch
* dev
  master
  • 修改readme.txt,并使用add和commit提交

  • 切换回master分支:

      $ git checkout master
    

切换回master分支后,再查看一个readme.txt文件,刚才添加的内容不见了!因为那个提交是在dev分支上,而master分支此刻的提交点并没有变
[图片上传失败...(image-a3e556-1519900739501)]

  • 把dev分支的工作成果合并到master分支上,git merge命令用于合并指定分支到当前分支。合并后,再查看readme.txt的内容,就可以看到,和dev分支的最新提交是完全一样的。注意到上面的Fast-forward信息,Git告诉我们,这次合并是“快进模式”,也就是直接把master指向dev的当前提交,所以合并速度非常快。当然,也不是每次合并都能Fast-forward,我们后面会讲其他方式的合并:
$ git merge dev
Updating 1f62bd2..8b89ed2
Fast-forward
 readme.txt | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)
  • 合并完成后,就可以放心地删除dev分支了:
$ git branch -d dev
Deleted branch dev (was 8b89ed2).
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,015评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,262评论 1 292
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,727评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,986评论 0 205
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,363评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,610评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,871评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,582评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,297评论 1 242
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,551评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,053评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,385评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,035评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,079评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,841评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,648评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,550评论 2 270

推荐阅读更多精彩内容