Git教程
> 参考 [黑马程序员Git全套教程](https://www.bilibili.com/video/BV1MU4y1Y7h5/?spm_id_from=333.999.0.0&vd_source=27c473f67063aa6a855a81b25ef650c9)
版本管理工具介绍
现在比较流行的版本管理工具是git ,但是实际上git 是近几年才发展起来的,可能有一些老的项目,还在用一些老的软件,比如svn
版本管理发展简史(维基百科)

SVN(SubVersion)
工作流程
1 | |
优缺点:
1 | |
svn流程图
Git
工作流程
1 | |
总结:git和svn的区别
1 | |
Git 发展简史
林纳斯·本纳第克特·托瓦兹(Linus Benedict Torvalds, 1969年~ )
很多人都知道,Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了。
Linus虽然创建了Linux,但Linux的壮大是靠全世界热心的志愿者参与的,这么多人在世界各地为Linux编写代码,那Linux的代码是如何管理的呢?
事实是,在2002年以前,世界各地的志愿者把源代码文件通过diff的方式发给Linus,然后由Linus本人通过手工方式合并代码!
你也许会想,为什么Linus不把Linux代码放到版本控制系统里呢?那个年代不是有CVS、SVN这些免费的版本控制系统吗?因为Linus坚定地反对CVS和SVN,这些集中式的版本控制系统不但速度慢,而且必须联网才能使用。有一些商用的版本控制系统,虽然比CVS、SVN好用,但那是付费的,和Linux的开源精神不符。
不过,到了2002年,Linux系统已经发展了十年了,代码库之大让Linus很难继续通过手工方式管理了,社区的弟兄们也对这种方式表达了强烈不满,于是Linus选择了一个商业的版本控制系统BitKeeper,BitKeeper的东家BitMover公司出于人道主义精神,授权Linux社区免费使用这个版本控制系统。而授权的前提是:Linux 社区的人不能开发具有相同功能的竞争产品!
另一方面,BitKeeper不是开源的. 显然与Linux 的开源精神不相符,所以linux 社区的很多人抱怨,不愿意使用.
典型的就是 Andrew Tridgell (Samba 开发服务的创造者) 非常不满.偷偷违反了和 BitKeeper 的协议,反编译 BitKeeper 的源代码,开发了个爬虫,然后爬取信息被人发现了. BitKeeper 公司的领导非常不满意,然后开始发布消息说,(下个版本)不再为Linux 提供免费的服务.
Linus 本人就出面协调(几周或者几个月),但是不管用, 没办法. 估计谈判的过程感觉到了憋屈–”吃人嘴短,拿人手软”
Linus 本人 花了10天的时间Git 出来了,一个月之内,Linux系统的源码已经由Git管理了!
Git 出来以后毕竟是一个人做的,开始并不好用(刚开始只能用勉强可以用来形容), 还是很多人抱怨,发展了很多年都没有干过其他软件.
直到 2008年,GitHub网站上线了,它为开源项目免费提供Git存储,无数开源项目开始迁移至GitHub,从此git 迎来了飞速发展,当下git 已经成为了最流行的版本控制工具
Git 工作流程
Git 初始化
命令行方式
cmd/iTerm 进入需要初始化的文件夹 执行 git init
客户端方式
我们先初始化一个本地仓
1 | |
此时 我们看到
1 | |
git 流程
流程图
概念即详解
1 | |
8.tag 标签
8.1 标签的概念
1 | |
8.2 标签的创建(tag)
1 | |
8.3 标签的切换与删除
9. 远程仓库
我们的代码不能总是放在本地,因为总是放在本地,一旦电脑出现故障,数据将丢失,怎么共享呢,这里我们需要一个服务器, 我们可以把代码放到服务器上,然后让别人下载,这样我峨嵋你既可以备份代码,也可以进行团队协作开发
9.0 局域网仓库
1 | |
9.0.1本地相对路径,多个文件夹之间共享代码
9.0.2开启局域网共享代码
局域网这种共享是没有安全控制的,都可以访问,如果想要搭建一个可以控制权限的服务器需要借助第三方软件
gitblit,可以自行搜索搭建
9.1 常用远程仓库托管服务
除了自己搭建服务器,其实我们可以使用一些免费的远程仓库,远程仓库有很多,常见的免费互联网远程仓库托管服务如下:
1 | |
鉴于国内用户可能网络不好,这里我们使用gitee(码云) 来讲解我们的课程,其他可自行找资料学习非常类似
9.2 码云账号注册
填写邮箱发送验证码,然后可以注册账号,主页如下
9.3 创建远程仓库
各个类型仓库之间的区别
9.4 把本地代码推送到远端
此时我们刷新仓库发现代码已经存在了
我们填写的用户信息,会被保存在本地,下次提交无需填写用户名和密码
9.5 从远程仓库克隆代码
我们同样可以从库下载代码,
新建一个文件夹 repo2 ,进入然后进行如下操作
此时我们发现我们的代码已经被下载下来了
9.6 代码的修改与提交,查看历史
1 | |
9.7 ssh 连接概述
1 | |
ssh 方式的底层原理
1 | |
9.8 ssh 密钥的生成
1 | |
9.9 ssh 密钥配置
9.10 ssh 方式克隆/提交代码:
配置完成之后我们克隆我们之前的项目
修改后直接提交推送即可成功,,git 会自动去.ssh 目录找我们的私钥进行匹配
9.11. 远程仓库的其他操作
概念
当我们从 gitee 上查看别人的项目的时候我们可能会看到上图中的按钮
1 | |
1 | |
项目操作
1)我们可以删除修改我们自己仓库的基本信息
- 我们可以邀请其他人成为项目的开发人员或者管理人员
我们可以删除修改我们自己仓库的基本信息
9.12 利用 gitee 搭建个人主页
1 | |
点击开启后gitee 会自动生成一个域名
直接访问即可
此时我们已经在git 上部署了一个静态的网站
10.命令行– git基本操作
10.1 介绍
上述我们的操作 使用的 是客户端TortoiseGit 操作的git ,实际上底层依旧是使用的命令行帮我们执行, 在早期 git 并没有窗口化工具,开发人员只能使用命令行模式
实际上,如果你掌握并熟练使用了命令行模式操作git 的话,你会发现某些操作命令行比窗口化操作要简单
所有你在工作中会发现高深的技术人员可能会喜欢命令行模式提交git
##10.2 环境配置
当安装Git后首先要做的事情是设置用户名称和email地址。这是非常重要的,因为每次Git提交都会使用该用户信息
1 | |
##10.3 初始化本地仓库 init
1 | |
##10.4 克隆 clone
1 | |
##10.5 查看状态 status
1 | |
##10.6 add
1 | |
##10.7 commit
1 | |
##10.8 删除 rm
1 | |
11. 命令行–git 远程仓库操作
11.1 查看远程
1 | |
11.2 添加/移除远测仓库
1 | |
11.3 从远程仓库获取代码
1 | |
注意:如果当前本地仓库不是从远程仓库克隆,而是本地创建的仓库,并且仓库中存在文件,此时再从远程仓库拉取文件的时候会报错(fatal: refusing to merge unrelated histories ),解决此问题可以在git pull命令后加入参数–allow-unrelated-histories (如上 命令)
1 | |
12. 命令行– 分支
1 | |
1 | |
13 . 命令行 –tag
1 | |
14. 案例
1 | |
概述
Git介绍
- Git是分布式版本控制系统
- 集中式VS分布式,SVN VS Git
- SVN和Git主要的区别在于历史版本维护的位置
- Git本地仓库包含代码库还有历史库,在本地的环境开发就可以记录历史而SVN的历史库存在于中央仓库,每次对比与提交代码都必须连接到中央仓库才能进行。
- 这样的好处在于:
- 自己可以在脱机环境查看开发的版本历史。
- 多人开发时如果充当中央仓库的Git仓库挂了,可以随时创建一个新的中央仓库然后同步就立刻恢复了中央库。
Git命令
Git配置
1 | |
git config命令的--global参数,表明这台机器上的所有Git仓库都会使用这个配置,也可以对某个仓库指定不同的用户名和邮箱地址。
创建版本库
初始化一个Git仓库
1 | |
添加文件到Git仓库
包括两步:
1 | |
git add可以反复多次使用,添加多个文件,git commit可以一次提交很多文件,-m后面输入的是本次提交的说明,可以输入任意内容。
查看工作区状态
1 | |
查看修改内容
1 | |
1 | |
1 | |
git diff可以查看工作区(work dict)和暂存区(stage)的区别git diff --cached可以查看暂存区(stage)和分支(master)的区别git diff HEAD -- <file>可以查看工作区和版本库里面最新版本的区别
查看提交日志
1 | |
简化日志输出信息
1 | |
查看命令历史
1 | |
版本回退
1 | |
以上命令是返回上一个版本,在Git中,用HEAD表示当前版本,上一个版本就是HEAD^,上上一个版本是HEAD^^,往上100个版本写成HEAD~100。
回退指定版本号
1 | |
commit_id是版本号,是一个用SHA1计算出的序列
工作区、暂存区和版本库
工作区:在电脑里能看到的目录;
版本库:在工作区有一个隐藏目录.git,是Git的版本库。
Git的版本库中存了很多东西,其中最重要的就是称为stage(或者称为index)的暂存区,还有Git自动创建的master,以及指向master的指针HEAD。
进一步解释一些命令:
git add实际上是把文件添加到暂存区git commit实际上是把暂存区的所有内容提交到当前分支
撤销修改
丢弃工作区的修改
1 | |
该命令是指将文件在工作区的修改全部撤销,这里有两种情况:
- 一种是file自修改后还没有被放到暂存区,现在,撤销修改就回到和版本库一模一样的状态;
- 一种是file已经添加到暂存区后,又作了修改,现在,撤销修改就回到添加到暂存区后的状态。
总之,就是让这个文件回到最近一次git commit或git add时的状态。
丢弃暂存区的修改
分两步:
第一步,把暂存区的修改撤销掉(unstage),重新放回工作区:
1 | |
第二步,撤销工作区的修改
1 | |
小结:
当你改乱了工作区某个文件的内容,想直接丢弃工作区的修改时,用命令
git checkout -- <file>。当你不但改乱了工作区某个文件的内容,还添加到了暂存区时,想丢弃修改,分两步,第一步用命令
git reset HEAD <file>,就回到了第一步,第二步按第一步操作。已经提交了不合适的修改到版本库时,想要撤销本次提交,进行版本回退,前提是没有推送到远程库。
删除文件
1 | |
git rm <file>相当于执行
1 | |
进一步的解释
Q:比如执行了rm text.txt 误删了怎么恢复?
A:执行git checkout -- text.txt 把版本库的东西重新写回工作区就行了
Q:如果执行了git rm text.txt我们会发现工作区的text.txt也删除了,怎么恢复?
A:先撤销暂存区修改,重新放回工作区,然后再从版本库写回到工作区
1 | |
Q:如果真的想从版本库里面删除文件怎么做?
A:执行git commit -m "delete text.txt",提交后最新的版本库将不包含这个文件
远程仓库
创建SSH Key
1 | |
关联远程仓库
1 | |
推送到远程仓库
1 | |
-u 表示第一次推送master分支的所有内容,此后,每次本地提交后,只要有必要,就可以使用命令git push origin master推送最新修改。
从远程克隆
1 | |
标签
tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起。
新建一个标签
1 | |
命令git tag <tagname>用于新建一个标签,默认为HEAD,也可以指定一个commit id。
指定标签信息
1 | |
git tag -a <tagname> -m "blablabla..."可以指定标签信息。
PGP签名标签
1 | |
git tag -s <tagname> -m "blablabla..."可以用PGP签名标签。
查看所有标签
1 | |
推送一个本地标签
1 | |
推送全部未推送过的本地标签
1 | |
删除一个本地标签
1 | |
删除一个远程标签
1 | |
版本管理
仓库管理
- 创建repository,mkdir/pws
- 初始化:git init
- 添加:git add
- 提交:git commit (
git commit命令,-m后面输入的是本次提交的说明,可以输入任意内容,当然最好是有意义的,这样你就能从历史记录里方便地找到改动记录) - 要随时掌握工作区的状态,使用
git status命令。如果git status告诉你有文件被修改过,用git diff可以查看修改内容 git log命令显示从最近到最远的提交日志; +”–pretty=oneline”简化输出- git reset –hard 🆔
git reflog用来记录你的每一次命令,用于版本回退
分支管理
创建分支
1
$ git branch <branchname>查看分支
1
$ git branchgit branch命令会列出所有分支,当前分支前面会标一个*号。切换分支
1
$ git checkout <branchname>创建+切换分支
1
$ git checkout -b <branchname>合并某分支到当前分支
1
$ git merge <branchname>删除分支
1
$ git branch -d <branchname>查看分支合并图
1
$ git log --graph当Git无法自动合并分支时,就必须首先解决冲突。解决冲突后,再提交,合并完成。用
git log --graph命令可以看到分支合并图。普通模式合并分支
1
$ git merge --no-ff -m "description" <branchname>因为本次合并要创建一个新的commit,所以加上
-m参数,把commit描述写进去。合并分支时,加上--no-ff参数就可以用普通模式合并,能看出来曾经做过合并,包含作者和时间戳等信息,而fast forward合并就看不出来曾经做过合并。保存工作现场
1
$ git stash查看工作现场
1
$ git stash list恢复工作现场
1
$ git stash pop丢弃一个没有合并过的分支
1
$ git branch -D <branchname>查看远程库信息
1
$ git remote -v在本地创建和远程分支对应的分支
1
$ git checkout -b branch-name origin/branch-name,本地和远程分支的名称最好一致;
建立本地分支和远程分支的关联
1
$ git branch --set-upstream branch-name origin/branch-name;从本地推送分支
1
$ git push origin branch-name如果推送失败,先用git pull抓取远程的新提交;
从远程抓取分支
1
$ git pull如果有冲突,要先处理冲突。
gitignore
技巧1:优化配置
Git 在全局、用户和本地级别上都是高度可配置的。
查找顺序
每个设置都可以被覆盖:
1 | |
修改配置
1 | |
显示当前设置
1 | |
一些有用的配置
1 | |
技巧2:别名(alias)
创建别名来保存常用的git命令:
1 | |
一些有用的别名
1 | |
技巧 3:查找 Commits 和更改
通过commits信息查找
1 | |
通过更改查找
1 | |
通过日期查找
1 | |
技巧4:添加hunk
git add
1 | |
技巧 5: 储藏(stash)更改而不提交
stash 将当前的更改临时搁置起来。在它的帮助下,可以返回当前状态的索引,并能在稍后应用已储藏的更改。
默认情况下,仅储藏当前跟踪文件中的更改,新文件将被忽略。
我们可以独立地创建和应用多个 stash。
创建
1 | |
罗列
1 | |
浏览
1 | |
应用
1 | |
清理
1 | |
技巧 6:空运行(Dry Run)
许多 git 操作可能具有破坏性,例如, git clean -f 将删除所有未跟踪的文件,而且无法恢复。
要避免出现这种灾难性的结果,许多命令都支持 dry-run ,可以在实际产生结果前对其进行检查。不过遗憾的是,使用的选项不完全一致:
1 | |
技巧 7:安全强制推送
在处理旧的 commit、创建新的 head 等情况时时很容易弄乱分支。 git push –force 可以覆盖远程变更,但不应该这样做!
git push –force 是一种具有破坏性且危险的操作,因为它无条件生效,并且会破坏其他提交者已经推送的所有 commit。这对于其他人的代码仓库来说不一定是致命的,但是改变历史记录并影响其他人并不是一个好主意。
更好的选择是使用 git push –force-with-lease 。
git 不会无条件地覆盖上游的远程仓库,而是检查是否有本地不可用的远程更改。如果有,它会失败并显示一条“stale info”消息,并告诉我们需要先运行 git fetch 。
技巧 8:修改 commit 信息
Commit 是不可变的,且不能更改。不过可以用一条新的 commit 信息修订现有的 commit,这会覆盖原始 commit,因此请勿在已推送的 commit 中使用它。
1 | |
技巧 9:修改历史
修改代码仓库的历史不仅限于修改上次提交信息,使用 git rebase 可以修改多个提交:
1 | |
在配置的编辑器中倒序列出所有的 commit,像这样:
1 | |
通过更改编辑器中的实际内容,可以为 git 提供一个方案,来说明如何进行 rebase:
1 | |
保存编辑器后,git 将运行该方案以重写历史记录。
e, edit 会暂停 rebase,就可以编辑代码仓库的当前状态。完成编辑后,运行 git rebase –continue 。
如果过程中出现问题(例如合并冲突),我们需要重新开始,可以使用 git rebase –abort 。
技巧 10:存档跟踪文件
可以使用不同格式( zip 或 tar )来压缩特定引用的跟踪文件:
1 | |
额外提醒:单破折号
有一个快捷方式可以表示刚用过的分支:一个单破折号 -
1 | |
单破折号等同于 @{-1} 。
[git-checkout](
Reference
[Git Pro](
`









































