Git基本操作

本文最后更新于:2021年3月3日 下午

概览:Git安装以及使用。

Git学习

Git是一个 分布式版本控制系统

  • 集中式版本控制:版本库集中存放在中央服务器,工作时需要用自己的电脑从中央服务器取得最新版本。
  • 分布式版本控制:没有“中央服务器”,每个人的电脑上都是一个完整的版本库,多人协作时只需将各自的修改推送给对方。
  • 实际使用时,分布式版本控制系统通常有一台电脑充当中央服务器,方便所有人交换修改。
  • 分布式版本控制的优点:可以不联网、可以不需要中央服务器、比集中式安全和及其强大的分支管理。

Git安装配置

Windows下直接去官网下载: https://git-scm.com/

安装完成后记得在命令行设置:

1
2
$ git config --global user.name "Your Name"
$ git config --global user.email "email@example.com"
  • 因为Git是分布式版本控制系统,所以,每个机器都必须自报家门:你的名字和Email地址。
  • --global参数,用了这个参数,表示你这台机器上所有的Git仓库都会使用这个配置 .

创建版本库

什么是版本库呢?版本库又名仓库,英文名repository,你可以简单理解成一个目录,这个目录里面的所有文件都可以被Git管理起来,每个文件的修改、删除,Git都能跟踪,以便任何时刻都可以追踪历史,或者在将来某个时刻可以“还原”。

  • 创建一个空目录,最好路径最好不要有中文。

  • 打开Git工具,在此目录下执行git init。这样一个空仓库就创建完成,路径下有一个.git目录。

    • .git目录是Git工具用于跟踪管理版本库的,不要随意修改。
  • 所有的版本控制系统都只能追踪文本文件的修改,可以告诉你每次的改动,但二进制文件就无法跟踪了。

添加文件到版本库中

例如在这个目录创建一个readme.md文件,然后编辑两行内容。

第一步:把文件添加进仓库

1
git add readme.md

无任何消息提示,说明添加成功

第二步:用命令告诉Git,把文件提交到仓库

1
git commit -m"wrote a readme file"

提示信息为

1
2
3
[master (root-commit) 2ddec99] wrote a reaeadme file
1 file changed, 3 insertions(+)
create mode 100644 readme.md
  • -m后面接本次提交的说明,最好输入有意义的内容。
  • 可以先add多个文件,然后commit

查看仓库的当前状态

当修改readme.md文档后,直接运行git status

1
2
3
4
5
6
7
On branch master
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git restore <file>..." to discard changes in working directory)
modified: readme.md

no changes added to commit (use "git add" and/or "git commit -a")
  • git status可以让我们得知仓库当前的状态。上述内容就告诉我们文件修改但未提交。

查看文档修改内容

使用git diff <filename>这个命令就可以查看和原内容的区别。

1
2
3
4
5
6
7
8
9
10
11
12
diff --git a/readme.md b/readme.md
index 00521b4..2a74408 100644
--- a/readme.md
+++ b/readme.md
@@ -1,3 +1,3 @@
-123
+Git is powerful too.

-456
\ No newline at end of file
+By Colourso.
\ No newline at end of file
  • 删去了123,增加了Git is powerful too.。……

提交修改

同提交新文件。

第一步:git add readme.md

第二步:git commit -m"……"

然后再查询状态git status

1
2
On branch master
nothing to commit, working tree clean

版本回退

查看commit记录

使用git log就可以查看git记录了,从最近到远。

  • 一长串的无规律字符是commit id,及版本号。
  • --pretty=oneline这个参数用来简化输出结果,只有版本号以及修改信息

同时还能看到我们commit的后接参数-m里的信息。

1
2
3
4
5
6
7
8
9
10
11
commit 5520407e2933d035fa2fbdfeb23e5599b6409fcc (HEAD -> master)
Author: Colourso <colourso@outlook.com>
Date: Thu May 14 16:32:14 2020 +0800

alter new content

commit 257d8d9e93d784c98162fdc3ae77a6f77dcec19a
Author: Colourso <colourso@outlook.com>
Date: Thu May 14 16:25:42 2020 +0800

wrote a readme file

HEAD 当前版本

在Git中,用HEAD表示当前版本,也就是最新的提交1094adb...(注意我的提交ID和你的肯定不一样),上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100

HEAD其实是指向当前版本的指针,下面的回退或者到未来的操作都是改变HEAD指针的指向。

回退上一版本

使用命令git reset

1
2
3
git reset --hard HEAD^

输出结果:HEAD is now at 257d8d9 wrote a readme file

这时再查询git log就会发现比上面少了一个记录,说明回退成功。

回到未来的版本

1
git reset --hard 552040 #只需要commit id的几位即可

如果找不到了commit id,可使用git reflog来找到你的命令,前面几位数字就是commit id的前几位。

1
2
3
4
5
6
$ git reflog
5520407 (HEAD -> master) HEAD@{0}: reset: moving to 5520
257d8d9 HEAD@{1}: reset: moving to HEAD^
5520407 (HEAD -> master) HEAD@{2}: reset: moving to HEAD
5520407 (HEAD -> master) HEAD@{3}: commit: alter new content
257d8d9 HEAD@{4}: commit (initial): wrote a readme file

工作区与暂存区的概念

  • 工作区:Working Directory,即我们创建的哪个文件夹。
  • 版本库:Repository,工作区里的.git目录,暂存区就存在其中。
  • 暂存区:叫stage,或者index。
  • 因为我们创建Git版本库时,Git自动为我们创建了唯一一个master分支,所以,现在,git commit就是往master分支上提交更改。

git add操作,实际是把文件添加到暂存区。

git commit操作,提交更改,将暂存区内容提交到。

  • 使用git status可以查看到未被添加的文件是Untracked
  • 提交修改以及新文件之后,使用git status就能看到nothing to commit, working tree clean

管理修改

git跟踪并管理的是修改,而非文件

当你修改文件并且git add之后,修改就会放入暂存区,而接着进行第二次修改,没有git add直接git commit的话,提交到master的是第一次修改的内容。

所以每次修改如果不主动git add添加到暂存区,那么修改也不会加入到commit中。

撤销修改

场景1:当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令git checkout -- file

  • 命令git checkout -- readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:
    • 一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
    • 一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
    • 总之,就是让这个文件回到最近一次git commitgit add时的状态。

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

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

删除文件

当把一个文件commit到仓库之后,在工作区删除了,使用git status就会看到这个文件是deleted

删除工作区文件后两种选择:

  1. 一起删除版本库中的文件。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    colou@LAPTOP-0MEIEISE MINGW64 /d/learn/git/helloworld3 (master)
    $ git rm hello.txt
    rm 'hello.txt'

    colou@LAPTOP-0MEIEISE MINGW64 /d/learn/git/helloworld3 (master)
    $ git commit -m"remove a txt file"
    [master ab13cff] remove a txt file
    1 file changed, 1 deletion(-)
    delete mode 100644 hello.txt
  2. 误删除,恢复误删的文件。(此时没有commit)

    1
    git checkout -- hello.txt

    这样就可以恢复删除的文件了,

    git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

远程仓库

配置SSH Key

为什么GitHub需要SSH Key呢?因为GitHub需要识别出你推送的提交确实是你推送的,而不是别人冒充的,而Git支持SSH协议,所以,GitHub只要知道了你的公钥,就可以确认只有你自己才能推送。

当然,GitHub允许你添加多个Key。假定你有若干电脑,你一会儿在公司提交,一会儿在家里提交,只要把每台电脑的Key都添加到GitHub,就可以在每台电脑上往GitHub推送了。

先检查自己电脑路径C:\Users\你的用户名\下是否有.ssh目录以及目录下是否有id_rsaid_rsa.pub两个文件,没有的话执行命令ssh-keygen -t rsa -C "youremail@example.com",邮箱填写自己的,一直回车即可。

如果已经有的话就直接登陆Github,在账户的设置中,选择SSH and GPG keys,然后起一个title,将刚才生成的id_rsa.pub文件使用记事本打开。复制内容粘贴到Key中,这样就添加完成。

可以使用命令ssh -T git@github.com来测试是否成功,这里不需要修改那个邮箱地址。有问题输入yes,然后如果出现类似You’ve successfully authenticated, but GitHub does not provide shell access.这种话就成功了。

添加一个远程库

以我要新建的仓库Collect-Simple-Web为例。

本地新建一个目录就叫做Collect-Simple-Web,然后将我收集整理好的文件放到这个目录中。

使用git工具,git init进行初始化。

然后执行git add .,意思是将所有的文件添加到暂存库。结果如下,会有一堆关于LF被替换成CRLF的警告,忽略就好。

1
2
3
4
$ git add .
warning: LF will be replaced by CRLF in 01 Self-adaption login page/assets/css/login.css.
The file will have its original line endings in your working directory
warning: LF will be replaced by CRLF in 01 Self-adaption login page/assets/libs/layui/css/layui.css.

然后git commit一下。

之后执行下列指令:

1
2
3
4
5
6
7
8
9
10
11
12
13
$ git remote add origin git@github.com:Colourso/Collect-Simple-Web.git

$ git push -u origin master
Enumerating objects: 183, done.
Counting objects: 100% (183/183), done.
Delta compression using up to 8 threads
Compressing objects: 100% (175/175), done.
Writing objects: 100% (183/183), 7.23 MiB | 127.00 KiB/s, done.
Total 183 (delta 4), reused 0 (delta 0)
remote: Resolving deltas: 100% (4/4), done.
To github.com:Colourso/Collect-Simple-Web.git
* [new branch] master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
  • origin是远程库的名字,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

  • 把本地库的内容推送到远程,用git push命令,实际上是把当前分支master推送到远程。

    由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。

  • 此后,每次本地commit后,只要有必要,就可以使用命令git push origin master推送最新修改;无需再加-u

从远程库克隆

1
git clone git@github.com:Colourso/Books.git

Github还提供了https地址来克隆,但是httpsssh协议要慢。

分支管理

分支在实际中有什么用呢?假设你准备开发一个新功能,但是需要两周才能完成,第一周你写了50%的代码,如果立刻提交,由于代码还没写完,不完整的代码库会导致别人不能干活了。如果等代码全部写完再一次提交,又存在丢失每天进度的巨大风险。

现在有了分支,就不用怕了。你创建了一个属于你自己的分支,别人看不到,还继续在原来的分支上正常工作,而你在自己的分支上干活,想提交就提交,直到开发完毕后,再一次性合并到原来的分支上,这样,既安全,又不影响别人工作。

创建与合并分支

链接: https://www.liaoxuefeng.com/wiki/896043488029600/900003767775424

包含相关图例

每次提交,Git都把它们串成一条时间线,这条时间线就是一个分支。截止到目前,只有一条时间线,在Git里,这个分支叫主分支,即master分支。HEAD严格来说不是指向提交,而是指向mastermaster才是指向提交的,所以,HEAD指向的就是当前分支。

Git用master分支指向最新的提交,再用HEAD指针指向master

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

这时候提交新的内容,全部都保存在dev分支上,如果切换到master分支的话,将不会看到修改变化的内容。

而当想合并devmaster分支时,直接修改master指针到dev最新的节点即可。

上述的切换分支、合并分支以及创建分支、删除分支等操作只需要修改修改指针、改变HEAD指针的指向即可,所以这些操作非常的快。

Git鼓励你使用分支完成某个任务,合并后再删掉分支,这和直接在master分支上工作效果是一样的,但过程更安全。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ git checkout -b dev 		# 创建并且切换到分支dev
Switched to a new branch 'dev'

$ git branch # 查看所有分支,*表示当前分支
* dev
master

# 在dev分支,提交相关东西、完成一个规划……

$ git checkout master # 切换当前分支到master分支
Switched to branch 'master'

$ git merge dev # 合并分支
Updating ab13cff..6c72d67
Fast-forward
……

$ git branch -d dev # 删除dev分支
Deleted branch dev (was 6c72d67).

Git鼓励大量使用分支:

查看分支:git branch

创建分支:git branch

切换分支:git checkout 或者git switch

创建+切换分支:git checkout -b 或者git switch -c

合并某分支到当前分支:git merge

删除分支:git branch -d

Git常用命令参考手册: https://github.com/xjh22222228/git-manual