Git到底怎么用?

Git归纳总结笔记

  • Git概述
    • 分布式&&集中式
    • 版本库(仓库)
    • 版本控制
    • 远程仓库
    • 分支管理
    • 标签管理
    • 参与一个GitHub开源项目

Git概述

Git是什么?Git是一套先进的分布式版本控制系统。他可以帮助我们记录在项目开发过程中的具体改动。

分布式&&集中式

在Linuxs开发Git系统时,其实当时已经有成熟可用的集中式版本控制系统,但由于集中式的种种缺陷,Linuxs不愿采用,于是在02年左右创造了开源的Git系统。

那么集中式和分布式有什么不同呢?

先说集中式版本控制系统,版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。中央服务器就好比是一个图书馆,你要改一本书,必须先从图书馆借出来,然后回到家自己改,改完了,再放回图书馆。

而分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,你工作的时候,就不需要联网了,因为版本库就在你自己的电脑上。既然每个人电脑上都有一个完整的版本库,那多个人如何协作呢?比方说你在自己电脑上改了文件A,你的同事也在他的电脑上改了文件A,这时,你们俩之间只需把各自的修改推送给对方,就可以互相看到对方的修改了。

版本库(仓库)

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

创建一个版本库

首先选择一个合适的地方,创建一个空目录:

上面我们先创建一个名为gitlib的目录。
通过git init 命令,将该目录变成git可管理的目录:

我们可以发现当前目录下多了一个.git的目录,这个目录是Git来跟踪管理版本库的。这个目录默认是隐藏的,使用ls -ah命令就可以看见。

我们现在试着创建一个文件添加到仓库中。
在刚刚的gitlib目录下,创建git.txt文件,输入一些内容。


我们使用vim创建名为git的txt文件,在里面输入了
Git is a version control system.
Git is free software.
的内容,使用git add命令将文件添加到仓库,使用commit进行提交,-m参数后面带上提交的信息,自定义,方便自己后续查看即可。
执行成功后,如图,他会告诉你一个文件被改动,影响行数等信息。因为我的文件中多加了个回车因此影响3行。

为什么Git添加文件需要add,commit一共两步呢?那是因为commit可以一次提交很多文件,所以你可以多次add不同的文件,比如:

$ git add file1.txt
$ git add file2.txt file3.txt
$ git commit -m "add 3 files."

版本控制

版本回退

现在我们试着修改我们的git.txt文件,我们原先的文件内容如下:

MacdeMacBook-pro-3:gitlib mac$ vim git.txt Git is a version control system.
Git is free software.

现在在version前加上distributed,保存后使用git status查看当前仓库状态如下:

MacdeMacBook-pro-3:gitlib mac$ 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:   git.txtno changes added to commit (use "git add" and/or "git commit -a")
MacdeMacBook-pro-3:gitlib mac$ 

可以看到这里显示我们修改了git.txt这个文件,但是还没有进行添加提交,我们可以先使用git diff命令查看我们队文件进行了什么修改:

MacdeMacBook-pro-3:gitlib mac$ git diff git.txt 
diff --git a/git.txt b/git.txt
index ec548e1..a5fc558 100644
--- a/git.txt
+++ b/git.txt
@@ -1,3 +1,3 @@
-Git is a version control system.
+Git is a distributed version control system.Git is free software.MacdeMacBook-pro-3:gitlib mac$ 

如上我们看到修改的地方为增加了distributed。确认修改内容后,进行添加提交后在查看状态。

 git add git.txt 
MacdeMacBook-pro-3:gitlib mac$ git commit git.txt "添加了distributed"
error: pathspec '添加了distributed' did not match any file(s) known to git
MacdeMacBook-pro-3:gitlib mac$ git commit git.txt -m "添加了distributed"
[master e0a8ab1] 添加了distributed1 file changed, 1 insertion(+), 1 deletion(-)
MacdeMacBook-pro-3:gitlib mac$ git status
On branch master
nothing to commit, working tree clean
MacdeMacBook-pro-3:gitlib mac$ 

再修改一次该文件,重新提交,此时,我们一共提交过了3个版本。
那么当我们修改次数多了,我们怎么记得我们每次修改的是什么,想要的是哪个版本呢?

git log命令帮助我们解决了这个问题:

MacdeMacBook-pro-3:gitlib mac$ git log
commit 2469cfa4a7f0366937ba820a0d8e24c5f6682e06 (HEAD -> master)
Author: mac <690661404@qq.com>
Date:   Fri Nov 1 17:12:03 2019 +0800修改第二行commit e0a8ab10c74c3a621468adc4fdcb27883afb6fa4
Author: mac <690661404@qq.com>
Date:   Fri Nov 1 16:46:57 2019 +0800添加了distributedcommit 74ff530f111a5b5a6633b6da8cf2565c2c3ea35c
Author: mac <690661404@qq.com>
Date:   Thu Oct 31 10:00:39 2019 +0800create a txtfile
MacdeMacBook-pro-3:gitlib mac$ 

他显示从最近到最远的提交日志,我们可以看到3次提交,最近的一次是修改第二行,上一次是添加了distributed,最早的一次是wcreate a txtfile。

需要友情提示的是,你看到的一大串类似e0a8a…的是commit id(版本号),和SVN不一样,Git的commit id不是1,2,3……递增的数字,而是一个SHA1计算出来的一个非常大的数字,用十六进制表示,而且你看到的commit id和我的肯定不一样,以你自己的为准。为什么commit id需要用这么一大串数字表示呢?因为Git是分布式的版本控制系统,后面我们还要研究多人在同一个版本库里工作,如果大家都用1,2,3……作为版本号,那肯定就冲突了。

现在我们如果要将git.txt文件回退一个版本,那么应该怎么做呢?

首先,Git必须知道当前版本是哪个版本,在Git中,用HEAD表示当前版本,也就是最新的提交e0a8a…,上一个版本就是HEAD^,前100个版本写成HEAD~100。

现在,我们要把当前版本append GPL回退到上一个版本添加了distributed,就可以使用git reset命令:

MacdeMacBook-pro-3:gitlib mac$ git reset --hard head^
HEAD is now at e0a8ab1 添加了distributed
MacdeMacBook-pro-3:gitlib mac$ cat git.txt 
Git is a distributed version control system.
Git is free software.
MacdeMacBook-pro-3:gitlib mac$ 

可见当前版本为第二个版本。但是再次git log查看版本:

MacdeMacBook-pro-3:gitlib mac$ git log
commit e0a8ab10c74c3a621468adc4fdcb27883afb6fa4 (HEAD -> master)
Author: mac <690661404@qq.com>
Date:   Fri Nov 1 16:46:57 2019 +0800添加了distributedcommit 74ff530f111a5b5a6633b6da8cf2565c2c3ea35c
Author: mac <690661404@qq.com>
Date:   Thu Oct 31 10:00:39 2019 +0800create a txtfile
MacdeMacBook-pro-3:gitlib mac$ 

我们发现最新版本的修改不见了!那么怎么回到最新版本呢?
还记得我们的commit id吧,只要记得我们的commit id,就能够回到最新版本:

MacdeMacBook-pro-3:gitlib mac$ git reset --hard 2469c
HEAD is now at 2469cfa 修改第二行
MacdeMacBook-pro-3:gitlib mac$ 

如果不记得你的commit id呢?也不要紧,使用git reflog命令查看历史命令:

MacdeMacBook-pro-3:gitlib mac$ git reflog
2469cfa (HEAD -> master) HEAD@{0}: reset: moving to 2469c
e0a8ab1 HEAD@{1}: reset: moving to head^
2469cfa (HEAD -> master) HEAD@{2}: commit: 修改第二行
e0a8ab1 HEAD@{3}: commit: 添加了distributed
74ff530 HEAD@{4}: commit (initial): create a txtfile
MacdeMacBook-pro-3:gitlib mac$ 

如上我们可以看到,我们每个命令对应的commit,那么你就可以根据commit将HEAD指向任意版本啦。

工作区和暂存区

工作区(Working Directory)
就是你在电脑里能看到的目录,比如我的gitlib文件夹就是一个工作区.

暂存区

我们查看工作区gitlib下的文件结构,可以看到其中有一个.git文件(默认隐藏):

MacdeMacBook-pro-3:gitlib mac$ ls -ah
.	..	.git	git.txt
MacdeMacBook-pro-3:gitlib mac$ 

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

前面讲了我们把文件往Git版本库里添加的时候,是分两步执行的:

第一步是用git add把文件添加进去,实际上就是把文件修改添加到暂存区;第二步是用git commit提交更改,实际上就是把暂存区的所有内容提交到当前分支。

管理修改

在Git中,它管理的是文件的修改而非文件!
我们现在试着修改git.txt文件,添加依据Git tracks changes.
进行git add添加到暂存区。接着再将文件最后一句话修改为Git tracks changes of file. 不进行添加,直接commit。会发现实际上提交到分支的为第一次修改的内容,即不带of file的内容,这就是git管理的为修改的简单证明。

撤销修改
在当前文件中插入一句话,当前我们的文件内容如下:

MacdeMacBook-pro-3:gitlib mac$ cat git.txt 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git tracks changes of file.
stupid svn.
MacdeMacBook-pro-3:gitlib mac$ 

那么如果我们要撤销插入的最后一行该怎么做呢?查看一下当前状态:

MacdeMacBook-pro-3:gitlib mac$ 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:   git.txtno changes added to commit (use "git add" and/or "git commit -a")
MacdeMacBook-pro-3:gitlib mac$ 

可以看到,git提示我们,可以使用git checkout – …命令来撤销我们当前的修改,如下:

MacdeMacBook-pro-3:gitlib mac$ git checkout --git.txt 
MacdeMacBook-pro-3:gitlib mac$ git status
On branch master
nothing to commit, working tree clean
MacdeMacBook-pro-3:gitlib mac$ cat git.txt 
Git is a distributed version control system.
Git is free software distributed under the GPL.
Git tracks changes of file.
MacdeMacBook-pro-3:gitlib mac$ 

命令git checkout – readme.txt意思就是,把readme.txt文件在工作区的修改全部撤销,这里有两种情况:

一种是readme.txt自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;

一种是readme.txt已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。

总之,就是让这个文件回到最近一次git commit或git add时的状态。

现在,看看readme.txt的文件内容:
当你已经将文件add到暂存区时,那么你需要多加一步git reset HEAD ,将文件从暂存区回退到工作区,再执行上述清除过程。

删除文件
现在我们添加一个test文件,并提交到分支中:

MacdeMacBook-pro-3:gitlib mac$ vim test.txt
MacdeMacBook-pro-3:gitlib mac$ git commit test.txt -m "新增了一个test文件"
error: pathspec 'test.txt' did not match any file(s) known to git
MacdeMacBook-pro-3:gitlib mac$ git add test.txt 
MacdeMacBook-pro-3:gitlib mac$ git commit test.txt -m "新增了一个test文件"
[master 717217f] 新增了一个test文件1 file changed, 1 insertion(+)create mode 100644 test.txt
MacdeMacBook-pro-3:gitlib mac$ 

那么现在如果需要将文件删除怎么做呢?首先将文件从文件系统中删除,这很简单:

MacdeMacBook-pro-3:gitlib mac$ rm test.txt 
MacdeMacBook-pro-3:gitlib mac$ ls
git.txt
MacdeMacBook-pro-3:gitlib mac$ 

那么接着从git仓库分支中删除:

MacdeMacBook-pro-3:gitlib mac$ git rm test.txt
rm 'test.txt'
MacdeMacBook-pro-3:gitlib mac$ git commit -m "删除了test文件"
[master 6ca0363] 删除了test文件1 file changed, 1 deletion(-)delete mode 100644 test.txt
MacdeMacBook-pro-3:gitlib mac$ git log
commit 6ca0363fe042c3c84ccd03a930b0c1ade51b527e (HEAD -> master)
Author: mac <690661404@qq.com>
Date:   Sun Nov 3 21:20:57 2019 +0800删除了test文件commit 717217f18e63d2c6353e7034fc54cffec78321de
Author: mac <690661404@qq.com>
Date:   Sun Nov 3 21:17:45 2019 +0800新增了一个test文件

从上述可见,只需使用git rm ,并执行提交即可。

另一种情况是删错了,因为版本库里还有呢,所以可以很轻松地把误删的文件恢复到最新版本:
$ git checkout – test.txt
git checkout其实是用版本库里的版本替换工作区的版本,无论工作区是修改还是删除,都可以“一键还原”。

远程仓库

添加远程仓库

这里我们可以使用GitHub来作为我们的远程托管仓库,创建好GitHub账号后,我们可以免费获得github远程仓库,由于本地仓库与远程仓库之间数据传输需要通过SSH加密,因此我们需要生成一下ssh密钥。

在我们的主目录中查看一下是否有.ssh这个文件夹,由于我之间已经创建过,因此这里是有该文件夹的:

可以看到这个文件夹中有 id_rsa,id_rsa.pub,这里对用的是ssh协议的密钥与公钥,关于ssh协议的验证原理这里不再赘述。

那么我们需要与GitHub仓库进行数据传输,那自然就要让GitHub知道我们的公钥了,登录后在GitHub官网上的设置中,添加公钥,结果如下:

这里添加了一个title为MySSHKey的公钥,title可随意取。

现在我们想要在GitHub也创建一个仓库,那么怎么做呢?
在GitHub官网右上角,找到new Repository选项,进去后输入仓库名,确认即可生成一个空的仓库。

现在我们关联本地仓库和该远程仓库:

MacdeMacBook-pro-3:gitlib mac$ git remote add origin git@github.com:Threadalive/myGitRepository.git
MacdeMacBook-pro-3:gitlib mac$ 

输入上述命令,关联本地与远程仓库,上面@后为你的GitHub账户名及仓库名。

添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的,但是origin这个名字一看就知道是远程库。

接下来就可以吧本地分支内容推送到远程仓库的分支上。

MacdeMacBook-pro-3:gitlib mac$ git push -u origin master
Enumerating objects: 21, done.
Counting objects: 100% (21/21), done.
Delta compression using up to 4 threads
Compressing objects: 100% (15/15), done.
Writing objects: 100% (21/21), 1.85 KiB | 945.00 KiB/s, done.
Total 21 (delta 4), reused 0 (delta 0)
remote: Resolving deltas: 100% (4/4), done.
To github.com:Threadalive/myGitRepository.git* [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.
MacdeMacBook-pro-3:gitlib mac$ 

现在,你就可以看到GitHub上与你本地一样的文件。

远程库克隆
我们已经知道了如何关联远程库,并将本地分支的更新push到远程库中,那么我们怎么将远程仓库中的项目直接克隆到本地仓库呢?

我们创建一个带描述文件的仓库:

然后输入clone命令:

MacdeMacBook-pro-3:Documents mac$ git clone git@github.com:Threadalive/GitClone.git
Cloning into 'GitClone'...
Warning: Permanently added the RSA host key for IP address '13.229.188.59' to the list of known hosts.
remote: Enumerating objects: 3, done.
remote: Counting objects: 100% (3/3), done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
Receiving objects: 100% (3/3), done.
MacdeMacBook-pro-3:Documents mac$ cd GitClone/
MacdeMacBook-pro-3:GitClone mac$ ls
README.md
MacdeMacBook-pro-3:GitClone mac$ 

可以看到该仓库已被克隆至本地。

实际上GitHub给出的地址不止一个,还可以用https://github.com/Threadalive/Clone.git这样的地址。实际上,Git支持多种协议,默认的git://使用ssh,但也可以使用https等其他协议。

分支管理

在我们之前的操作中,不管是提交或是版本回退,都是在一条分支上进行,即master分支,前面我们说了,git中用head指针指向当前版本,而master指针指向当前分支,那么他是怎么做到的呢?

答案即如上图所示,git用master指针指向当前版本的结点,有将HEAD指针指向master指针每当我们新提交一个版本,master指针就会向后移动一个结点。

我们知道git是支持多分支协同操作的,并且速度极快,那么首先,我们怎么创建并使用一条分支呢?

这里git给我们提供了两条命令:

git checkout -b NewBranch
git switch -c NewBranch

上述NewBranch为新分支的名称。

我们创建并切换至新分支,其实也就是创建了一个NewBranch指针指向当前版本结点,并把HEAD指针指向该新指针:

MacdeMacBook-pro-3:GitClone mac$ git branch
* master
MacdeMacBook-pro-3:GitClone mac$ ls
README.md
MacdeMacBook-pro-3:GitClone mac$ git checkout -b NewBranch
M	README.md
Switched to a new branch 'NewBranch'
MacdeMacBook-pro-3:GitClone mac$ ls
README.md
MacdeMacBook-pro-3:GitClone mac$ git branch
* NewBranchmaster
MacdeMacBook-pro-3:GitClone mac$ vim README.md 
MacdeMacBook-pro-3:GitClone mac$ git add README.md 
MacdeMacBook-pro-3:GitClone mac$ git commit -m "branch test"
[NewBranch 11ecae8] branch test1 file changed, 2 insertions(+), 1 deletion(-)
MacdeMacBook-pro-3:GitClone mac$ git checkout master
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
MacdeMacBook-pro-3:GitClone mac$ git branchNewBranch
* master
MacdeMacBook-pro-3:GitClone mac$ cat README.md 
# GitCloneMacdeMacBook-pro-3:GitClone mac$ git merge NewBranch
Updating 9ea49a6..11ecae8
Fast-forwardREADME.md | 3 ++-1 file changed, 2 insertions(+), 1 deletion(-)
MacdeMacBook-pro-3:GitClone mac$ cat README.md 
# GitClone
on NewBranch
MacdeMacBook-pro-3:GitClone mac$ git branch -d NewBranch
Deleted branch NewBranch (was 11ecae8).
MacdeMacBook-pro-3:GitClone mac$ git brabch
git: 'brabch' is not a git command. See 'git --help'.The most similar command isbranch
MacdeMacBook-pro-3:GitClone mac$ git branch
* master
MacdeMacBook-pro-3:GitClone mac$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 257 bytes | 257.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To github.com:Threadalive/GitClone.git9ea49a6..11ecae8  master -> master
MacdeMacBook-pro-3:GitClone mac$ 

以上,我们创建了一个名为NewBranch的新分支,并在该分支中对README文件进行了修改,添加到暂存区,进行提交,接着切换回master分支,查看当前文件状态,接着合并NewBranch分支,再次查看,发现文件已是更新后的形式。最后删除NewBranch分支,将版本推送至GitHub仓库。

版本冲突的解决

我们可以看到上述合并的方式为Fast-forward,快速合并,那是因为我们在master分支中并没有修改我们的文件,git只需要将master指针指向NewBranch指针指向的版本结点即可。

那么如果我们在当前master中也对文件进行了修改,就会导致合并时发生冲突,我们可以使用git status查看冲突的文件,手动修改内容后,再次合并。

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

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

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

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

所以,团队合作的分支看起来就像这样:

一般来说,在团队合作开发中,我们遵循这样的工作模式:

  1. 首先,可以试图用git push origin 推送自己的修改;

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

  3. 如果合并有冲突,则解决冲突,并在本地提交;

  4. 没有冲突或者解决掉冲突后,再用git push origin 推送就能成功!

  5. 如果git pull提示no tracking information,则说明本地分支和远程分支的链接关系没有创建,用命令git
    branch --set-upstream-to origin/。

标签管理

我们有时候可能需要对某个操作做一个记号,git为我们提供了标签的操作:

MacdeMacBook-pro-3:GitClone mac$ git branch
* divmaster
MacdeMacBook-pro-3:GitClone mac$ git tag version1.0
MacdeMacBook-pro-3:GitClone mac$ git tag
version1.0
MacdeMacBook-pro-3:GitClone mac$ git show version1.0
commit 11ecae84da1ac3742c435064c2c33058cde4ea02 (HEAD -> div, tag: version1.0, origin/master, origin/HEAD, master)
Author: mac <690661404@qq.com>
Date:   Sun Nov 10 13:30:01 2019 +0800branch testdiff --git a/README.md b/README.md
index c5c24df..8bed2d4 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,2 @@
-# GitClone
\ No newline at end of file
+# GitClone
+on NewBranch
MacdeMacBook-pro-3:GitClone mac$ 

上面操作中,我们对当前分支打上了version1.0的标签,并用git show命令查看了标签信息。

如果标价打错了,也可以进行删除:

MacdeMacBook-pro-3:GitClone mac$ git tag -d version1.0
Deleted tag 'version1.0' (was 11ecae8)
MacdeMacBook-pro-3:GitClone mac$ 

如果是对远程库进行标签操作,git提供如下方法:

  • 命令git push origin --tags可以推送全部未推送过的本地标签;
  • 命令git push origin :refs/tags/可以删除一个远程标签。

参与一个GitHub开源项目

众所周知,GitHub上拥有众多优秀的开源项目,那么我们怎么进行参与呢?

在GitHub网站上,进入项目主页点击Fork,便可克隆一个该项目到自己的GitHub仓库,接下来,你需要将该项目克隆到本地,你可以自己进行修改或者添加功能,在push到自己的远程仓库中,若你想让作者根据你的意见更新,那么可以发起一个pull request请求,当然接不接受就要看作者咯。

END

本文链接:https://my.lmcjl.com/post/13311.html

展开阅读全文

4 评论

留下您的评论.