一文掌握git基本使用

版本控制

版本控制的功能

  1. 协同修改
    可以多人并行不悖地修改服务器同一个文件
  2. 数据备份
    不仅保存目录和文件的当前状态,还能够保存每一个提交过的历史状态
  3. 版本管理
    在保存每一个版本的文件信息的时候要做到不保存重复数据,以节约存储空间,提高运行效率。这方面 SVN 采用的是增量式管理的方式,而 Git 采取了文件系统快照的方式
  4. 权限控制
    对团队中参与开发的人员进行权限控制
  5. 历史记录
    查看修改人、修改时间、修改内容、日志信息
  6. 分支管理
    允许开发团队在工作过程中多条生产线同时推进任务,进一步提高效率

集中式版本控制

集中式版本控制工具:CVS、SVN、VSS等,其中SVN用途比较广泛。
集中式版本控制系统的版本库是集中存放在中央服务器的,而干活的时候,用的都是自己的电脑,所以要先从中央服务器取得最新的版本,然后开始干活,干完活了,再把自己的活推送给中央服务器。
在这里插入图片描述
集中式版本控制最大的问题就是必须联网才能工作,如果网速过慢会带来很大的不便。另外也存在单点故障的问题,即服务器崩溃导致工作无法进行。

分布式版本控制

分布式版本控制工具:Git、Mercurial、Bazaar、Darcs等。
分布式版本控制系统根本没有“中央服务器”,每个人的电脑上都是一个完整的版本库,这样,工作的时候,就不需要联网了,因为版本库就在自己的电脑上。但是为了工作方便,分布式版本控制系统通常也有一台充当“中央服务器”的电脑,但这个服务器的作用仅仅是用来方便“交换”大家的修改,没有它大家也一样干活,只是交换修改不方便而已。
在这里插入图片描述

Git 简介

Git是目前世界上最先进的分布式版本控制系统,它是由linus用C语言开发而来,其产生依托于Linux,所以具有Linux学习基础的同学对于Git的学习会更得心应手。

Git 的优势

Git作为目前世界上最先进的分布式版本控制系统,其具有很多优势:

  1. 大部分操作在本地完成,不需要联网
  2. 完整性保证
  3. 尽可能添加数据而不是删除或修改数据
  4. 分支操作非常快捷流畅
  5. 与 Linux 命令全面兼容

Git 的结构

Git 由工作区、暂存区、本地仓库组成。
工作区可以看作是写代码的区域;
暂存区可以看作临时存储区;
本地仓库存储着历史版本。

在这里插入图片描述
Workspace:工作区
Index:暂存区
Repository:本地仓库
Remote:远程仓库

Git 安装

在Linux上安装Git

对于Debian或Ubuntu Linux,通过一条sudo apt-get install git就可以直接完成Git的安装,非常简单。
在这里插入图片描述

在Windows上安装Git

可以从Git官网上直接下载。

安装之后的设置

由于Git是分布式版本控制系统,每一台机器在安装完Git之后需要设置签名用以区分不同开发人员的身份。
在命令行输入git config --global user.name "your name"git config --global user.email "your email"来设置用户名和邮箱。
在这里插入图片描述

创建版本库

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

在空目录下创建版本库,会默认创建一个隐藏的.git目录,用来存放版本库的全部源元素。
在这里插入图片描述

基本操作

添加(git add [文件名])

git add [文件名] 该命令是将工作区的“新建/修改的文件”添加到暂存区。
在这里插入图片描述
将文档readme.txt添加到暂存区,只需要输入git add readme.txt即可,没有任何提示则说明添加成功。

提交(git commit -m “message”)

git commit -m "commit message" [文件名] 将暂存区的内容提交到本地库。
也可以不加[文件名],git commit -m "commit message" 表示把暂存区所有内容提交到本地库。
在这里插入图片描述
git commit命令执行成功后会显示:

  • 1 file changed:1个文件被改动(新添加的readme.txt文件);
  • 2 insertions:插入了两行内容(readme.txt有两行内容)

状态查看(git status)

git status可以查看仓库当前的状态

当修改了readme.txt内容之后没有git add,查看仓库当前状态
在这里插入图片描述
git add之后
在这里插入图片描述
git commit之后
在这里插入图片描述

比较文件差异(git diff)

当我们再次修改文件内容之后,利用git status,Git只会告诉我们文件被修改了,但是无法知道修改了什么内容。利用git diff可以看到文件内容修改了什么。

readme.txt文件内容修改,利用git diff [文件名]查看内容的改变:
在这里插入图片描述
git diff 也可以不加参数:

  • 当暂存区中没有文件时,git diff比较的是,工作区中的文件与上次提交到版本库中的文件。
  • 当暂存区中有文件时,git diff则比较的是,当前工作区中的文件与暂存区中的文件。

git diff --cached 比较暂存区和本地仓库文件的区别
git diff HEAD 比较的是工作区中的文件与版本库中文件的差异(当前分支上)
git diff 18f822e 比较指定版本号 和当前工作目录的差异
git diff new 将当前分支和指定分支new对比

查看历史记录(git log)

当多次修改文件之后,可以利用git log来获取历史记录
在这里插入图片描述
git log命令显示从最近到最远的提交日志,每个提交有四部分信息:版本号、提交人、提交日期、提交留言
当日志显示信息过多,可以通过多屏显示控制方式:

  • 空格向下翻页
  • b 向上翻页
  • q 退出

git log --pretty=oneline可以精简地显示日志信息
在这里插入图片描述
git log --oneline 可以精简地显示版本号和日志信息:
在这里插入图片描述
git log 版本号 传递一个指定的版本,并以此作为查看日志的起始点(查看从那时起到现在的全部提交):
在这里插入图片描述
git reflog记录每一次命令
在这里插入图片描述其中:HEAD@{移动到当前版本需要多少步}

git log --since="5 hours"查看最近5小时内的提交

前进后退(git reset)

  • 基于版本号操作(推荐)
    git reset --hard [版本号]
    在这里插入图片描述
    输入git log --oneline查看日志,:
    在这里插入图片描述
  • 使用^符号:只能后退
    git reset --hard HEAD^ 表示退回到上一个版本
    注:一个^表示后退一步,n 个表示后退 n 步
  • 使用~符号:只能后退
    git reset --hard HEAR~n 表示后退n步

reset三个命令参数的对比

在这里插入图片描述

删除文件

在这里插入图片描述
工作区和版本库不一致了,git status命令告诉你test.txt被删除了

现在分为两种情况:

  1. 删错了,因为版本库里还有test.txt,所以可以很轻松地把误删的文件恢复到最新版本:
    git checkout -- test.txt
    在这里插入图片描述
  2. 确实要从版本库中删除该文件,那就用命令git rm删掉,并且git commit
    在这里插入图片描述

撤销修改

未git add添加到暂存区

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

当在readme.txt修改内容后,想撤回修改
在这里插入图片描述
使用git checkout -- readme.txt丢弃工作区的改动
在这里插入图片描述
此时的readme.txt内容和之前相同

已git add添加到暂存区

readme.txt文件内容修改之后,并且添加到了暂存区,还没有提交,用命令git reset HEAD <file>可以把暂存区的修改撤销掉,重新放回工作区
在这里插入图片描述

已git commit提交到版本库

已经提交了不合适的修改到版本库时,想要撤销本次提交,参考前面的前进后退命令,不过前提是没有推送到远程库

分支管理

什么是分支?

在项目开发的过程中,有时需要添加新功能、测试新算法、修正新bug等,如果只有一条版本演进的轨迹,则很难实现,引入分支可以使得在版本控制过程中,使用多条线同时推进多个任务。
分支的好处:

  • 同时并行推进多个功能开发,提高开发效率
  • 各个分支在开发过程中,如果某一个分支开发失败,不会对其他分支有任何影响,失败的分支删除重新开始即可
    在这里插入图片描述

**Git鼓励开发人员频繁地使用分支:**由于Git的分支实质上仅是包含所指对象校验和(长度为40的SHA-1值字符串)的文件,所以它的创建和销毁都异常高效。创建一个新分支就像是往一个文件中写入41个字节(40 个字符和1个换行符),所以Git创建分支非常快。
这与过去大多数版本控制系统形成了鲜明的对比,它们在创建分支时,将所有的项目文件都复制一遍,并保存到一个特定的目录。完成这样繁琐的过程通常需要好几秒钟,有时甚至需要好几分钟。所需时间的长短,完全取决于项目的规模。而在Git中,任何规模的项目都能在瞬间创建新分支。同时,由于每次提交都会记录父对象,所以寻找恰当的合并基础(译注:即共同祖先)也是同样的简单和高效。这些高效的特性使得Git鼓励开发人员频繁地创建和使用分支。

创建分支(git branch/git checkout -b [分支名])

命令git branch [分支名] 创建分支
命令git checkout -b [分支名]表示创建并切换分支,相当于执行git branch [分支名]git checkout [分支名]
在这里插入图片描述
在这里插入图片描述

切换分支(git checkout [分支名])

git checkout [分支名] 可以切换到相应的分支
在这里插入图片描述

查看分支(git branch)

git branch命令会列出所有分支,当前分支前面会标一个*
在这里插入图片描述

合并分支(git merge [分支名])

当我们在dev分支对readme.txt内容进行修改和提交后,回到master分支发现readme.txt内容并没有发生改变,因为那个提交是在dev分支上,而master分支此刻的提交点并没有变:
在这里插入图片描述
dev上的工作完成了,就可以回到master分支上,利用命令git merge devdev合并到master在这里插入图片描述
实现的过程如下:
在这里插入图片描述

删除分支(git branch -d/D [分支名])

合并完成后,就可以利用命令git branch -d dev删除dev分支了,删除之后只剩master分支了
在这里插入图片描述

在这里插入图片描述

git branch -D [分支名] 强行删除未合并的分支。

git switch

切换分支使用git checkout <branch>,而前面讲过的撤销修改则是git checkout -- <file>,容易引起混淆,因此,最新版本的Git提供了新的git switch命令来切换分支:
创建并切换到新的dev分支,可以使用:git switch -c dev
直接切换到已有的master分支,可以使用:git switch master

解决冲突

当在分支feature1上修改了readme.txt文件内容后,在分支feature1上进行提交;切换回master分支,又再次修改了readme.txt文件内容后,在分支master上进行提交,此时进行分支合并会发生冲突。
在这里插入图片描述
在这里插入图片描述
readme.txt文件存在冲突,必须手动解决冲突后再提交。git status也可以告诉我们冲突的文件:
在这里插入图片描述
我们可以直接查看readme.txt的内容:
在这里插入图片描述
修改master分支下的readme.txt内容,使其与分支feature1的内容相同,即可以完成合并分支
在这里插入图片描述
现在,master分支和feature1分支变成了下图所示:
在这里插入图片描述
最后删除feature1分支,工作完成。
在这里插入图片描述

git log --graph命令可以看到分支合并图
在这里插入图片描述
冲突的解决:

  1. 编辑文件,删除特殊符号
  2. 把文件修改到满意的程度,保存退出
  3. git add [文件名]
  4. git commit -m "日志信息"
    注意:此时 commit 一定不能带具体文件名

分支管理策略

通常,合并分支时,Git会默认用Fast forward模式,但这种模式下,删除分支后,会丢掉分支信息。
如果加上--no-ff参数就可以用普通模式合并,强制禁用Fast forward模式,Git就会在merge时生成一个新的commit,这样,从分支历史上就可以看出分支信息。
在这里插入图片描述
使用git log --graph --pretty=oneline --abbrev-commit查看分支历史:
在这里插入图片描述
可以看到,不使用Fast forward模式,merge后就像这样:
在这里插入图片描述

Bug分支

修复bug时,我们会通过创建新的bug分支进行修复,然后合并,最后删除;
当手头工作没有完成时(即在分支dev上),先把工作现场git stash一下,然后去修复bug,修复后,再git stash pop,回到工作现场(分支dev)。

流程:

  1. dev分支工作时遇到Bug需要返回master分支,先把工作现场git stash一下,然后返回master分支修复Bug:
    在这里插入图片描述

  2. master分支创建issue-101分支解决Bug:
    在这里插入图片描述

  3. git stash pop,恢复工作现场:
    在这里插入图片描述

dev分支是早期从master分支分出来的,所以,这个Bug其实在当前dev分支上也存在,所以需要在dev分支上修复同样的Bug。
master分支上修复的Bug,想要合并到当前dev分支,可以用git cherry-pick <commit>命令,把bug提交的修改“复制”到当前分支,避免重复劳动:
在这里插入图片描述

远程仓库

通过SSH连接远程仓库

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

ssh-keygen -t rsa -C "[email protected]"

创建成功之后,可以在用户主目录里找到.ssh目录,里面有id_rsaid_rsa.pub两个文件,这两个就是SSH Key的秘钥对,id_rsa是私钥,不能泄露出去,id_rsa.pub是公钥,可以放心地告诉任何人。

第2步:登陆GitHub,打开“Account settings”,“SSH Keys”页面,然后,点“Add SSH Key”,填上任意Title,在Key文本框里粘贴id_rsa.pub文件的内容,点击“Add Key”即可。
在这里插入图片描述

添加远程库

目的:将已有的本地仓库和远程库进行同步
首先在github上创建一个新的仓库"learngit"
在这里插入图片描述
目前,在GitHub上的这个learngit仓库还是空的,可以把一个已有的本地仓库与之关联,然后,把本地仓库的内容推送到GitHub仓库。
在本地的learngit仓库下运行命令:

$ git remote add origin git@github.com:tkzky/learngit.git

添加后,远程库的名字就是origin,这是Git默认的叫法,也可以改成别的。
下一步,就可以把本地库的所有内容推送到远程库上:

$ git push -u origin master
Counting objects: 20, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (15/15), done.
Writing objects: 100% (20/20), 1.64 KiB | 560.00 KiB/s, done.
Total 20 (delta 5), reused 0 (delta 0)
remote: Resolving deltas: 100% (5/5), done.
To github.com:michaelliao/learngit.git
 * [new branch]      master -> master
Branch 'master' set up to track remote branch 'master' from 'origin'.

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

由于远程库是空的,我们第一次推送master分支时,加上了-u参数,Git不但会把本地的master分支内容推送的远程新的master分支,还会把本地的master分支和远程的master分支关联起来,在以后的推送或者拉取时就可以简化命令。
此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改到远程库。

从远程库克隆

上一节时先有本地库,后有远程库的时候,进行关联远程库。本节是从远程库克隆一份到本地库。
在远程库已经存在的前提下用命令git clone克隆一个本地库:

$ git clone git@github.com:tkzky/gitskills.git
Cloning into 'gitskills'...
remote: Counting objects: 3, done.
remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 3
Receiving objects: 100% (3/3), done.

然后进入gitskills目录,就是本地库,可以进行工作了。

查看远程库信息(git remote)

git remote命令可以查看远程库的信息:

$ git remote
origin

git remote -v可以显示更详细的信息:

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

面显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址。

推送分支(git push)

推送分支,就是把该分支上的所有本地提交推送到远程库。推送时,要指定本地分支,这样,Git就会把该分支推送到远程库对应的远程分支上:

$ git push origin master

如果要推送其他分支,比如dev,就改成:

$ git push origin dev

但是,并不是一定要把本地分支往远程推送,那么,哪些分支需要推送,哪些不需要呢?

  • master分支是主分支,因此要时刻与远程同步;
  • dev分支是开发分支,团队所有成员都需要在上面工作,所以也需要与远程同步;
  • bug分支只用于在本地修复bug,就没必要推到远程了,除非老板要看看你每周到底修复了几个bug;
  • feature分支是否推到远程,取决于你是否和你的小伙伴合作在上面开发。

抓取分支(git pull)

git pull是相当于从远程仓库获取最新版本,然后再与本地分支合并。
git pull = git fetch + git merge

git pull origin master 把远程的master分支拉取并用merge的方式合并到本地分支上

git pull origin master:new 把远程的master分支拉取并用merge合并到本地的new分支上

git pull -r origin master:new 把远程的master分支拉取并用rebase的方式合并到本地的new分支上

删除远程分支

假设你已经通过远程分支做完所有的工作了并且将其合并到了远
程仓库的 master 分支(或任何其他稳定代码分支)。可以运行带有 --delete 选项的 git push 命令来删除一个远程分支。
如果想要从服务器上删除 feature1分支,运行下面的命令:

$ git push origin --delete feature1

关于Git的基本使用暂时总结到这里,日后会逐渐丰富内容,感谢廖雪峰老师的Git教程和蓝桥实验室!

猜你喜欢

转载自blog.csdn.net/tkzky001/article/details/108988357