Git完全入门指南

Git完全入门指南

教程参考

廖雪峰Git教程

三十分钟入门Git

概述

Git是项目版本管控的工具,可以用来追踪,记录文件的变动,无论你是自己一个人做项目还是多人协作项目, 都是十分必要的工具。

git一般用来:

  1. 备份自己项目中的每一次修改
  2. 将自己的项目上传到远程服务器和别人一同协作
  3. 合并自己和别人对同一个项目的修改
  4. 找回过去的项目版本

笔者会结合自身项目中常用的命令和一个简单的实例一步步来带新手进入git的世界。

Git安装

Ubuntu

一行命令搞定

sudo apt-get install git

Windows

Git官网上下载安装程序, 按默认选项安装即可,安装完成后在开始菜单中找到git bash, 说明git安装完成!

安装完成之后要进行设置。设置自己的名字和自己的邮箱。

打开git bash

image.png

在git bash命令行中输入

$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"

--global表示对该机器上的所有git版本库都使用这个配置。

这里的名字可以比较随意,但邮箱一定要填自己常用的那个,因为之后我们需要用来登录github并提交到github远程服务器。

基本使用

创建git版本库 - git init

配置完成之后我们就要开始在本地创建自己的git版本库了。

我们先进入一个目录并调出git bash

cd D:\\Document\\git-test
git init

现在在git-test文件夹下就多了一个.git文件夹,这个.git文件夹里面便会去记录我们文件的每一次修改。

查看工作区状态 - git status

我们把现在的除了.git文件夹的区域称之为工作区, 因为我们的项目就是放在这个目录下的,我需要查看当前工作区的状态则使用git status命令。

$ git status
On branch master

Initial commit

nothing to commit (create/copy files and use "git add" to track)

这里输出了三行字,我们一行一行来理解

  1. 当前我们在master分支
  2. 初始化提交
  3. 没有文件需要提交

分支

分支是git中的一个概念,可以理解为树中的枝干,而在我们刚创建一个git版本库的时候我们处于的是master分支,也叫主分支,分支的概念在后面会提到。

第一行指我们现在处于的是主分支的开发环境, 第二句话指我们刚刚做了初始化git版本库的操作。第三句话是指当前缓冲区中没有文件需要提交。关于缓冲区这个我们也稍后再说。我们先试着添加一个文件。

$ touch git-test.md

创建一个叫git-test.md的文件,再执行git status

$ git status
On branch master

Initial commit

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

        git-test.md

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

前两句话是一样的就不解释了, 第三句话就很重要了,Untracked files, 没有追踪到的文件,

然后下面是git-test.md,也就是我们刚刚创建文件,再下面告诉我们没有添加提交但未跟踪的文件存在,

其实这里就是告诉我们git-test.md还没有在我们的git版本库中,他的修改等不会被git版本库追踪。

那么我们赶紧把git-test.md加入git版本库进行追踪吧。

添加到暂存区 - git add

添加到版本库分为两步,第一步是添加到暂存区,执行下面的指令。

$ git add git-test.md

git add 文件名即为将文件添加到暂存区了, 如果要添加当前目录下的所有文件用 git add -a

再执行 git status

$ git status
On branch master

Initial commit

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

        new file:   git-test.md


发现原来的git-test.md没有被追踪的提示消失了,反而提示 被提交的改变为:新文件: git-test.md

也就是说git版本库已经知道我们创建了一个新的文件了。

接下来还没完,这只是放在暂存区,还没有真正的保存。真正的保存需要用git commit来确认一次提交

确认提交 - git commit

添加到版本库的第二步是确认提交,确认提交是我们工作进行到一定程度,一般是完成了一个小功能,想保存一下进度的时候做的,这时候我们顺便会记录一下我们做过的工作,所以git commit一般这么写

$ git commit -m "创建了新文件git-test.md"
[master (root-commit) b989378] 创建了新文件git-test.md
 1 file changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 git-test.md


-m 即message, 表示提交信息

这里也有3行,主要理解一下前2行:

  1. master分支下进行了一次提交,提交信息为"创建了新文件git-test.md", 本次提交的版本号为b989378,这个版本号我们也稍后再详细解释
  2. 提交中有1个文件变化,0个插入,0个删除

很好,这次提交达到了我们想要的效果。

再执行git status

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


这次直接提示我们,没有文件需要提交,工作树是干净的。到此我们的一次工作记录就完成了。

git add 和git commit

git add其实已经将你的修改保存下来了, 为什么还要git commit呢, 用游戏类比的话, add 只是推荐游戏的进行, 但是并没有对游戏存档, 如果我们想要存档,并可能在以后回到这个存档点,我们就需要手动进行一次存档,这就是git commit了。你是没办法回到上一个add的操作点,但是可以回到commit的操作点。回到存档点的方法我们稍后再说。


我们再来一遍相似的操作。首先我们修改git-test.md的文本内容,添加两行字

学习git

hello world

然后我们查看下暂存区和工作区文件的不同。

查看不同 - git diff

我们可以用git diff来查看git跟踪的文件的变化。

$ git diff
diff --git a/git-test.md b/git-test.md
index e69de29..e13761d 100644
--- a/git-test.md
+++ b/git-test.md
@@ -0,0 +1,3 @@
+学习git
+
+hello world

主要关注最后两行, -0,0意思是0到0行被删除了,也就是没有行删除。+1,3意思为1到3行被添加了,添加的内容为学习git空行,hello world。所以我们用git diff指令就能看出来我们工作区相对版本库的改变,相对版本库,也就是说是执行了git add之后的改变(git add即进入版本库的第一步), 你现在可以试试输入git add之后再输入git diff,这次就什么都不会输出了。因为工作区和版本库是同步的了。

继续执行commit来确认提交

$ git commit -m "添加了两行文字"
[master a26ff1d] 添加了两行文字
 1 file changed, 3 insertions(+)

这里之所以有个空行是因为我用的markdown编辑器在换行的时候会自动插入一个空行。

回到过去 - git log; git reset

存档已经有了,我们该试着读档了。假设我们不小心删掉了第二行hello world, 但是我们想回到上一个有hello world的时候。首先我们需要查看我们的存档表。

$ git log
commit a26ff1da8e69bb2afbd386c24c57706f2175852d
Author: Acring <392398434@qq.com>
Date:   Mon Mar 26 11:27:24 2018 +0800

    添加了两行文字

commit b9893787f3cdadecb17e6c0cce0020b3c5a38256
Author: Acring <392398434@qq.com>
Date:   Sun Mar 25 22:30:04 2018 +0800

    创建了新文件git-test.md


这里显示了每一次提交的信息,包括

  1. 提交版本号
  2. 作者
  3. 提交日期
  4. 提交信息

我们需要的是版本号,比如这里的有hello world 的存档的版本号为a26ff1da8e69bb2afbd386c24c57706f2175852d, 我们也不用全部记住,其实只需要前几位就行了,接下来用git reset来读档。

$ git reset --hard a26ff
HEAD is now at a26ff1d 添加了两行文字

他告诉我们HEAD(头指针)已经指向了我们的a26ff1d开头的存档了,再看看我们的git-test.md文件,是不是hello world又回来了。

graph LR
    a((b989378))-->b((a26ff1d))
    b---c((删除hello world))
    h(HEAD)-->c

git中的改变可以看做一条链表,而我们工作处于HEAD(头指针)所指向的那个修改。改变HEAD的位置也就改变了工作区的内容了。

版本回退还有revert checkout 等方法,reset只是相对比较简单的方法,如果有兴趣可以去了解其他的方法,不过版本回退在开始一般用得比较少

无视文件 - .gitignore

在实际项目中有些文件是不需要被提交到git版本库的,比如自己服务器的配置文件(不想开源的时候被人看到), 第三方包文件夹(文件太大,上传太慢)等等,这时候我们就需要用.gitignore文件去过滤掉这些文件或文件夹。

首先新建一个文件.gitignore 不需要后缀, 然后用文本编辑器打开并添加一行,

ignored.md

意思是我们准备无视掉这个叫ignored.md的文件。 接着我们创建这个ignored.md文件,里面有没有内容都没关系。

用git bash 执行命令git add ignored.md

$ git add ignored.md
The following paths are ignored by one of your .gitignore files:
ignored.md
Use -f if you really want to add them.

可以看到add失败了,git提示我们当前路径已经被.gitignore文件设定为无视了,无法被add添加到版本库,除非用-f指令强制执行。有了.gitignore我们就可以放心的用git add -a添加所有文件了, 因为git会自动把.gitignore中提到的文件或文件夹过滤掉不添加。gitignore的语法规则可以自己去百度,其实还是比较简单的。


以上都是笔者在本地git实践中比较常用的命令了,其实并不多,add commit 是最主要的。

接下来要开始将git搬上远程服务器进行实践了。


注册github

为啥我们要使用github,github是啥?这是我们需要首先明白的问题。

github提供了一个git服务器,这样我们就不需要自己买一台远程服务器了,但是github为你免费提供服务器的代价是你的项目是公开的,如果不想公开的话必须购买付费服务,你可以把自己的开源项目通过git上传到git服务器,并为这个项目创建一个主页用来分享自己开源项目。

使用github首先我们需要到官网注册,注册过程就不多加赘述了,注册完成之后我们需要让github知道我们的计算机是哪台。也就是说我们允许哪台计算机修改这个账号所拥有的开源项目

github是基于SSH协议来认证计算机的,具体感兴趣可以自己去了解SSH协议, 现在我们只需要知道,我们需要提供一个公钥给github, 这个公钥是在我们本地计算机生成的。

生成方法如下, 进入git bash

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

这里的邮箱改成自己的邮箱。之后一路回车,使用默认值。

注意在生成的过程中会显示他的生成路径, 比如我的是(/c/Users/Acring/.ssh/id_rsa), 记住这个地址

之后查看自己计算机的上述的.ssh路径,但是我们要用的不是id_rsa,这个是私钥,是不能泄露出去的,我们要用的是id_rsa.pub公钥,打开之后把里面的字符全选复制。

公钥有了,接下来就是把这个公钥告诉github让github知道我的这台计算机有权利管理github上该账号的项目了。

在github中进入Setting->SSH and GPG keys

image.png

点击New SSH Keys, 随便输入一个Title用来标识自己的计算机,将刚刚复制的公钥粘贴进去Key里, 点击Add SSH key保存就行了。

本地和远程同步

接下来我们就要把之前我们编辑的git-test项目上传到github上了。首先我们需要在github上建立一个空的远程git版本库。

image.png

按顺序填写版本库信息,点击Create repository完成创建。

image.png

注意上面画圈的地方, 后面的URL是这个远程git版本库的地址,前面是上传项目过程中用的连接协议,我们就选SSH协议,好处是不需要每次上传都输入github账号密码,因为我们已经通过SSH Key告诉了github我们现在这台计算机是有项目管理权限的。顺便这个地址我们复制下来。马上就要用到了。

远程版本库创建完毕,但是现在本地的版本库还不知道有一个远程版本库哇,我们需要把他们两个关联起来

回到本地, 在原来的项目git-test目录下打开git bash(如果你在开始菜单打开git bash则会处于用户主目录下,要用cd跳转路径), windows下可以在项目目录中点击鼠标右键,可以看到一个git bash,可以很方便的打开。

image.png

添加远程版本库地址 - git remote add

之后我们要给本地版本库添加远程服务器地址,这里的远程版本库地址你要改成刚刚自己复制的地址

$ git remote add origin git@github.com:Acring/git-test.git

一般没有输出就代表关联成功了,解释一下:

remote add, 表示添加远程服务器, origin是一个标记,也可以用你喜欢的,习惯性使用origin表示主远程服务器,因为一个项目可能有多个远程版本库。这句话就表示添加一个以origin命名的远程版本库, 版本库地址为git@github.com:Acring/git-test.git


好了,现在本地已经知道远程版本库的地址了,我们可以把本地项目推送到远程版本库了,推送也就是上传本地版本库中的所有文件,注意是版本库,并不是工作区。

推送 - git push

推送需要用到git push,推送之前要确保所有的修改都被commit提交了,防止遗漏。

$ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 489 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:Acring/git-test.git
 * [new branch]      master -> master


git push 命令后面需要两个参数,一个是远程版本库的地址,我们之前已经设定了origin远程版本库的地址,所以这里用origin,接着是要提交的本地的分支名称,上面文章我提到了当创建版本库的时候我们默认是在master分支,所以这里写master分支的概念先不用懂。知道我们默认处于master分支就行了。

SSH警告

当你第一次使用Git的clone或者push命令连接GitHub时,会得到一个警告:

The authenticity of host 'github.com (xx.xx.xx.xx)' can't be established.
RSA key fingerprint is xx.xx.xx.xx.xx.
Are you sure you want to continue connecting (yes/no)?

这是因为Git使用SSH连接,而SSH连接在第一次验证GitHub服务器的Key时,需要你确认GitHub的Key的指纹信息是否真的来自GitHub的服务器,输入yes回车即可。

Git会输出一个警告,告诉你已经把GitHub的Key添加到本机的一个信任列表里了:

Warning: Permanently added 'github.com' (RSA) to the list of known hosts.

这个警告只会出现一次,后面的操作就不会有任何警告了。


接下来我们要演示的是当两个计算机协同工作时可能出现的情况以及如何去解决。

克隆远程项目 - git clone

回到Github上刚刚我们的项目网页, 刷新,我们发现git-test.md文件以及被推送上来了,那要是我们想从另一台计算机上获取下来呢,这时候就要用到我们的git clone命令了.

image.png

首先我们还是需要远程版本库的地址,可以用上面我们复制好的,也可以在项目主页的Clone or download中找到远程版本库地址。其实和之前的是一样的。

image.png

换一个路径来假装是另一台计算机,比如我现在切换到了D:\CODE\github路径下。在当前目录重新打开git bash。执行克隆命令

$ git clone git@github.com:Acring/git-test.git
Cloning into 'git-test'...
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 6 (delta 0), reused 6 (delta 0), pack-reused 0
Receiving objects: 100% (6/6), done.

克隆下来之后会发现多了一个git-test文件夹,里面有我们的git-test.md文件。克隆成功!

github上的开源项目是谁的可以克隆的,你也可以用这个命令来克隆别人的开源项目。

B电脑修改并推送

这次我们对刚刚克隆下来的项目进行修改并重新推动到远程版本库, 假装新的路径属于电脑B

我们把git-test.md中的hello world改成, hello acring,并保存。

之后add,commit, 二连提交本次修改。

$ git add git-test.md

$ git commit -m "修改为hello acring"
[master 66c6021] 修改为hello acring
 1 file changed, 1 insertion(+), 1 deletion(-)

然后我们再执行git push origin master将本地的修改推送到远程版本库,这里要注意,现在clone到的是我们已经在github上提交过公钥的电脑,所以能直接push提交,如果是另一台电脑的话需要再将那台电脑的公钥提交给github,否则github是不会给你随便提push的。

A电脑修改并推送

$ git push origin master
Counting objects: 3, done.
Writing objects: 100% (3/3), 280 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:Acring/git-test.git
   a26ff1d..66c6021  master -> master

提交完成之后在原本地版本库也修改一下, 把hello world改成 hello zzq,同样保存,add,commit,

再push上去,在push之前思考一下,**两台电脑都会hello world这一行做了修改,B电脑已经提交上去了,这时候A电脑要是提交上去会怎么样呢,那到底用A电脑的hello zzq呢,还是B电脑的hello acring呢。

这样一看似乎会乱套,我们先不管,先试着提交。

$ git push origin master
To github.com:Acring/git-test.git
 ! [rejected]        master -> master (non-fast-forward)
error: failed to push some refs to 'git@github.com:Acring/git-test.git'
hint: Updates were rejected because the tip of your current branch is behind
hint: its remote counterpart. Integrate the remote changes (e.g.
hint: 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

rejected!提交被拒绝了,因为git发现B电脑修改了项目并提交了,而A电脑也修改了项目企图提交,那就会发生项目很多不一致问题,比如上面说的hello world的选择问题。

先拉取再提交 - git pull

为了解决可能的冲突问题,A电脑需要先将远程版本库的项目拉取下来进行整合,整合完成之后再提交,这次我们不是克隆整个项目,而是在本地版本库的基础上更新远程版本库的内容。

$ git pull origin master
From github.com:Acring/git-test
 * branch            master     -> FETCH_HEAD
Auto-merging git-test.md
CONFLICT (content): Merge conflict in git-test.md
Automatic merge failed; fix conflicts and then commit the result.

这里有一个很重要的单词,merge,合并,当拉取远程版本库的项目时,git会首先去自动合并同一个被修改的文件。

比如这里的git-test.md,假如B电脑修改的不是hello world而是第一行学习git,那两者对同一个文件的修改其实是不冲突的,git会同时选择AB电脑的修改,比如假设B修改的是学习git-->不学习git合并后的git-test.md就变成了

不学习git

hello zzq

当然现在的情况显然没有那么乐观,回头看看提示

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

自动合并失败,请修复冲突(conflicts)并提交最终的修改结果。

是的,git处理不了两个电脑对hello world的修改,叫我们自己来做定夺了。

打开git-test.md

image.png

如果用的是Typora请点击下面的标签切换到源文本格式,否则Typora会把界面渲染的很奇怪: )

<<<<<<< HEAD
hello zzq
=======
hello acring
>>>>>>> 66c602160211831315b0a6f8eb17f3cc9cf49cf1

主要关注这几行,======上面是A电脑的修改,下面是B电脑的修改,折中一下,我们修改成下面这样那些奇怪的箭头什么的都删掉吧。

hello zzq&acring

修改完成别忘了add,commit二连。

$ git add git-test.md

Acring@DESKTOP-UBU88S4 MINGW64 /d/Document/git-test (master|MERGING)
$ git commit -m "merge hello world"
[master 9fe6b47] merge hello world

好了,接着再push

$ git push origin master
Counting objects: 6, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (6/6), 530 bytes | 0 bytes/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To github.com:Acring/git-test.git
   66c6021..9fe6b47  master -> master


这次就没什么问题了。以下是整个过程的流程图,可以重新梳理以下整个过程,并加深对各个命令的理解。

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

推荐阅读更多精彩内容

  • Git 基础 基本原理 客户端并不是只提取最新版本的文件快照,而是把代码仓库完整的镜像下来。这样一来,任何一处协同...
    __silhouette阅读 15,754评论 5 147
  • Git常用语法 [TOC] Git简介 描述 ​ Git(读音为/gɪt/。)是一个开源的分布式版本控制系统,...
    君惜丶阅读 3,442评论 0 13
  • 最近玩了款动作游戏,崩坏学园,哈哈,这名字起的真遛,分分钟崩盘。 想了想以前打过的游戏,从三国群英到红色警戒,从帝...
    Braysonowen阅读 258评论 0 0
  • 山里飞水电站的朋友打来电话,说家杀过年猪,请去玩。盛情之下,推脱不得,便应承了。次日早,与二朋友结伴而去。有进山的...
    血色岸标阅读 189评论 0 1
  • 凌晨3点被陈阿姨叫醒,睡了一觉这条腿总算恢复了知觉,我们四个急急忙忙把东西往包里面塞,咦,阿土伯来line消息,问...
    拍谢少女阅读 1,138评论 0 51