git学习记录(超详细-新手必看)

2,062 阅读8分钟

前言

1 git是做什么的?

Git是目前世界上最先进的分布式版本控制系统(没有之一),其实就是源代码管理工具。

2 什么是分布式版本控制系统?

先来看看集中式版本控制(svn cvs)

版本库是集中存放在中央服务器的,只有一个中央控制,所有的开发人员都必须依赖于这个代码仓库。每次版本控制的操作也必须链接到服务器才能完成。(必须联网 上传效率 安全问题)

再来看看分布式版本控制(git)

简单的说,分布式版本控制系统根本没有"中央服务器",分布式的版本控制就是每个人都可以创建一个独立的代码仓库用于管理,各种版本控制的操作都可以在本地完成。每个人修改的代码都可以推送合并到另外一个代码仓库中。(本地不依赖网 高效 安全)


开始git的体验吧!

1 安装git

在官网下载安装 一路next下来 git官网

配置环境变量

例如:我的git所在路径是 D:\火狐下载\Git 那么我需要把git下的bin目录和cmd目录添加进系统环境变量即可 D:\火狐下载\Git\binD:\火狐下载\Git\cmd

在命令行输入 git --version可以查看git版本

2 初始化git目录(创建版本库)

git init命令

示例(接下来的例子全部在gitdemo目录下)

$ git init
Initialized empty Git repository in C:/Users/lenovo/Desktop/gitdemo/.git/

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

3 查看状态

git status命令

$ git status
On branch master
Initial commit
Untracked files:
  (use "git add <file>..." to include in what will be committed)
        index.html
nothing added to commit but untracked files present (use "git add" to track)

第一次查看 显示的是一组没有被跟踪的文件 比如我的目录下的'index.html'

4 添加文件到暂存区(添加被git跟踪的文件)

为了我的源文件能被git管理 第一步就是需要添加到暂存区

git add命令 这里分为两种情况: 1)首次添加跟踪 2)修改代码后添加

先说第一种情况:

我现在要把'index.html'第一次提交到暂存区

使用$ git add index.html

此时让我们再来查看状态

$ git status

$ git status
On branch master
Initial commit
Changes to be committed:
  (use "git rm --cached <file>..." to unstage)
        new file:   index.html

显示一个新文件已经被添加到暂存区被git跟踪了

问题来了 项目下的文件很多 难道我们需要一个个的手动把需要跟踪的文件添加到暂存区吗?

当然不是 我们可以用 git add .命令 将目录里面的全部文件添加到暂存区

可是 有很多的文件我们是不需要跟踪的

例如:项目依赖包 node_module目录

我们可以添加一个本地git忽略清单

在项目目录的根文件夹创建一个以'.gitignore'命名的文件 然后在里面直接可以写忽略的文件夹 或者忽略的文件路径

第二种情况:

比如上面的index.html已经添加到暂存区 然后我现在改变了里面的一处代码 我该怎么再次提交到暂存区呢?

仍然可以使用 git add 'index.html'

或者将项目下所有的文件变动一次性提交 使用 git add --all

5 添加文件到版本库当前分支

成功把文件添加到暂存区了 但是这并不代表你把文件添加到版本库分支里面了

还需要git commit命令

$ git commit -m 'first updata'
[master (root-commit) a73f689] first updata
 1 file changed, 10 insertions(+)
 create mode 100644 index.html

简单解释一下git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录。

6 工作区 暂存区的关系

工作区:就是我们的项目文件夹不包括.git隐藏文件夹的区域

暂存区:Git的版本库里存了很多东西,其中最重要的就是称为stage(或者叫index)的暂存区。 还有Git为我们自动创建的第一个分支master,以及指向master的一个指针叫HEAD。

7 查看修改日志(提交历史)

git log命令

$ git log
commit a73f6890fa66a68919b57707505b597c7cd8761b (HEAD -> master)
Author: 小旭 <908130255@qq.com>
Date:   Tue Jun 6 15:09:10 2017 +0800
    first updata

说明: commit a73f6890fa66a68919b57707505b597c7cd8761b是commit id(版本号)

first updata是我们当时commit -m ''自己输入的引号内的信息

8 版本回退

假如我修改了很多次代码 提交了很多的不同版本到我的本地版本库分支master上 可是我发现最后一个有问题 我需要回到之前的版本怎么办?

这时候需要使用命令 git reset --hard 编号(编号就是上节说的commit id(版本号) 不需要写出完整的版本号 一般前8位以上就ok了)

$ git reset --hard a73f6890fa
HEAD is now at a73f689 first updata

此时版本已经回退到指定的版本号了 你可以看看你工作区的文件 是不是回到了之前的修改(神奇!)

9 查看文件差异

git diff命令

每次工作区修改完成后可以使用(对比本地文件一开始的样子)

$ git diff
diff --git a/index.html b/index.html
index 50c3720..9052a59 100644
--- a/index.html
+++ b/index.html
@@ -1,6 +1,7 @@
 <!DOCTYPE html>
 <html lang="en">
   <head>
+    <h2>nihao</h2>
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <meta http-equiv="X-UA-Compatible" content="ie=edge">

10 撤销修改

分为三种情况

1)只在工作区修改了 没提交到暂存区 $ git checkout -- index.html撤销工作区修改(其实 git checkout -- file 就是用暂存区的版本来代替工作区的版本)

2)修改提交到暂存区之后 又修改了

先使用$ git reset HEAD index.html 将暂存区的修改撤销掉,重新放回工作区,然后重复1)中的命令

3)已经提交到本地的版本库分支master上了(前提是没推送到远程版本库)

使用版本回退

11 删除文件

分为两种情况:

1)误删

使用 $ git checkout -- index.html

2)确实要删

使用 $ git rm index.html

$ git rm index.html
rm 'index.html'

然后 $ git commit -m 'delete index.html'使本地版本库的当前分支删除文件

$ git commit -m 'delete index.html'
[master 4e36418] delete index.html
 1 file changed, 11 deletions(-)
 delete mode 100644 index.html

12 开始远程连接(团队合作核心)

之前介绍的都是停留在本地仓库 也就是说不需要联网就可以进行操作 接下来进行远程仓库学习

查看自己的ssh密钥

$ ls -al ~/.ssh

$ ls -al ~/.ssh
total 30
drwxr-xr-x 1 lenovo 197121    0 6月   2 10:40 ./
drwxr-xr-x 1 lenovo 197121    0 6月   6 10:50 ../
-rw-r--r-- 1 lenovo 197121 1675 5月  27 18:39 github_rsa
-rw-r--r-- 1 lenovo 197121  404 5月  27 18:39 github_rsa.pub
-rw-r--r-- 1 lenovo 197121 1675 6月   2 10:40 id_rsa
-rw-r--r-- 1 lenovo 197121  398 6月   2 10:40 id_rsa.pub
-rw-r--r-- 1 lenovo 197121 1187 6月   5 15:25 known_hosts

看看有没有id_rsa和id_rsa.pub这两个文件,如果已经有了,可以直接将id_rsa.pub文件里的内容复制一份到剪切板

如果没有 那么需要创建SSH Key

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

你需要把邮件地址换成你自己的邮件地址,然后一路回车,使用默认值即可,由于这个Key也不是用于军事目的,所以也无需设置密码。

接下来在用户主目录里找到.ssh目录,里面有id_rsa和id_rsa.pub两个文件,这两个就是SSH Key的密钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

在git服务器上面绑定公钥

登录GitHub,打开"Account settings","SSH Keys"页面

点"Add SSH Key",填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容,点"Add Key",你就应该能看到已经添加的Key。

13 仓库远程同步

此时我们已经有一个本地版本库了 但是我们没有与远程库建立联系 所以我们的代码只有自己一个人知道 不能分享与合作

我之前在github上面建立了一个git-demo的仓库

使用$ git remote add origin 你的仓库ssh地址将远程库和自己的本地库连接

$ git remote add origin git@github.com:BigSharkLx/git-demo.git

连接成功后查看远程仓库地址 git remote -v

$ git remote -v
origin  git@github.com:BigSharkLx/git-demo.git (fetch)
origin  git@github.com:BigSharkLx/git-demo.git (push)

14 推送本地分支到github分支上

第一次提交时使用 git push -u origin master(-u是使用流形式 速度更快 提交到远程库主分支master上)

$ git push -u origin master
Counting objects: 3, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 449 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:BigSharkLx/git-demo.git
   f665eb1..97f9675  master -> master

如果git远程库已经存在内容(不是空的),新关联的本地库第一次提交代码是不被允许的 会报错如下:

$ git push -u origin master
To github.com:BigSharkLx/git-demo.git
 ! [rejected]        master -> master (fetch first)
error: failed to push some refs to 'git@github.com:BigSharkLx/git-demo.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.

这时候有两种方法解决

1) git push origin master -f 强推(利用覆盖的方式用本地代码替代git仓库内容 简单粗暴 后果自负)

2) 先将远程库的东西fetch到本地 然后再merge(效果等同于git pull)

15 克隆远程库代码

别人写好的代码你可以把他们克隆到自己的本地目录 git clone 仓库地址

$ git clone git@github.com:BigSharkLx/git-demo.git
Cloning into 'git-demo'...
remote: Counting objects: 6, done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 1), reused 5 (delta 0), pack-reused 0
Receiving objects: 100% (6/6), done.
Resolving deltas: 100% (1/1), done.

一般情况下你克隆的代码是没有权限push到别人的代码库的(因为别人的github账号并没有添加你电脑的公钥)

16 分支

分支就是指互不干扰的一条代码时间轴

查看分支

我们有本地分支和远程库分支 怎么查看分支呢

可以使用 git branch查看本地分支

$ git branch
* dev
  master

(前面的*代表当前选定的分支)

也可以查看所有分支(包括远程库的分支) git branch -a

$ git branch -a
* dev
  master
  remotes/origin/dev
  remotes/origin/master

创建分支

git branch 分支名

切换分支

git checkout 分支名

创建并切换一步到位

git checkout -b 分支名

合并分支

git merge 分支名

$ git merge dev
Already up-to-date.

删除分支

删除本地分支: git branch -d 分支名

$ git branch -d dev
Deleted branch dev (was 97f9675).

删除远程库分支: git push origin --delete 分支名

$ git push origin --delete dev
To github.com:BigSharkLx/git-demo.git
 - [deleted]         dev

在实际开发中,我们应该按照几个基本原则进行分支管理:

首先,master分支应该是非常稳定的,也就是仅用来发布新版本,平时不能在上面干活;

那在哪干活呢?干活都在dev分支上,也就是说,dev分支是不稳定的,到某个时候,比如1.0版本发布时,再把dev分支合并到master上,在master分支发布1.0版本;

你和你的小伙伴们每个人都在dev分支上干活,每个人都有自己的分支,时不时地往dev分支上合并就可以了

17 多人协作

多人协作的工作模式通常是这样:

首先,在本地创建和远程分支对应的分支,使用 git checkout -b 分支名 origin/分支名,本地和远程分支的名称最好一致

然后,建立本地分支和远程分支的关联,使用 git branch --set-upstream 分支名 origin/分支名

现在,可以试图用 git push origin 分支名推送自己的修改;

如果推送失败,则因为远程分支比你的本地更新,需要先用 git pull试图合并;

如果合并有冲突,则解决冲突,并在本地提交;没有冲突或者解决掉冲突后,再用 git push origin 分支名推送就能成功!

18 标签

标签说白了就是方便我们记忆和管理的,因为你不可能去记住 你每次提交的commit id(版本号)所以你只需要打上一个标签

创建标签

$ git tag 标签名 默认是为我们最后一次commit创建标签

如果想为每次commit创建标签怎么办呢

很简单 拿到commit id(版本号)就行

$ git tag 标签名 版本号

查看标签

git tag查看所有存在的标签

$ git tag
log
v0.9
v1.0

git show 标签名查看具体的某一个标签

$ git show v2.0
tag v2.0
Tagger: 小旭 <908130255@qq.com>
Date:   Wed Jun 7 11:05:25 2017 +0800

新升级了一些功能

commit 97f96751df5eafc7d53718802aa5e019ff789b26 (HEAD -> master, tag: v2.0, tag: v1.0, tag: log, origin/master)
Author: 小旭 <908130255@qq.com>
Date:   Wed Jun 7 08:58:32 2017 +0800

    new updata

添加标签信息

$ git tag -a 标签名 -m '描述信息'

删除标签

1)删除本地标签

$ git tag -d 标签名

2)删除远程库标签

git push origin :refs/tags/标签名

$ git push origin :refs/tags/v0.9
To github.com:BigSharkLx/git-demo.git
 - [deleted]         v0.9

远程推送标签

git push origin 标签名

$ git push origin v2.0
Counting objects: 1, done.
Writing objects: 100% (1/1), 186 bytes | 0 bytes/s, done.
Total 1 (delta 0), reused 0 (delta 0)
To github.com:BigSharkLx/git-demo.git
 * [new tag]         v2.0 -> v2.0

或者一次性推送全部的标签

$ git push origin --tags

$ git push origin --tags
Total 0 (delta 0), reused 0 (delta 0)
To github.com:BigSharkLx/git-demo.git
 * [new tag]         v0.9 -> v0.9
 * [new tag]         v1.0 -> v1.0

19 团队合作权限问题

解决方案一:把开发人员的电脑ssh公钥添加到项目负责人的git服务器账号上 这样就有push权限

解决方案二:建立一个组织,分别赋予组织成员push权利

20 想修改陌生人代码

你需要先fork别人的项目到自己的远程仓库 之后在你的本地仓库修改提交到远程 最后在别人的项目地址pull request 至于别人能否接受你的修改 那就不知道了