前言
本文行文将力求实用,详细,易懂,结合工作场景,将工作中遇到的最常用的git相关知识点做一总结。既是对git相关知识体系的一次梳理,又能分享给有需要的小伙伴进行学习提升。因本人能力水平有限,如有错误和建议,欢迎在评论区指出。若本篇文章有帮助到了您,不要吝啬您的小手还请点个赞再走哦!
1 起步
1.1 git是什么
Git是一个版本管理控制系统(缩写VCS),它可以在任何时间点,将文档的状态作为更新记录保存起来,也可以在任何时间点,将更新记录恢复回来。
1.2 安装
官网(速度贼慢)
淘宝镜像(速度快)
安装完检查一下版本 git --version
2 相关配置
2.1 使用前配置
配置使用者的用户名和邮箱,配置信息默认存储在:C:\Users\【当前电脑用户名】\.gitconfig 中
为了方便多人协作,所以需要设置用户
配置用户名
git config --global user.name 提交人姓名
配置邮箱
git config --global user.email 提交人邮箱
查看git配置信息
git config --list
注意: 如果要对配置信息进行修改,重复上述命令即可配置只需要执行一次
2.2 ssh免登录(以github为例)
实现原理:
将自己电脑中的私钥和github中的公钥进行配对,配对成功就不用输入账号密码了,所以只需要生成一次,配置完成后此电脑中的任何项目上传到自己的仓库都不需要登陆了
生成私钥和公钥
在要生成ssh 秘钥的项目中打开git ,输入ssh-keygen, 一直按回车就会在
C:\Users\【当前电脑用户名】\.ssh 中生成私钥和公钥对.
将电脑中的公钥放到 github 中就能免密码上传了
将C:\Users\【当前电脑用户名】\.ssh 中 id_rsa.pub 文件中的字符 复制到 github 的
(右上角 settings / ssh and GPG keys / New SSH key/)的 key 输入框中
RSA 是一种非对称加密方式
使用
在 github 仓库中 Clone or download 中点击 Use SSH 就能获取到 SSH 对应的地址了,然后就能免密码克隆或推送了
2.3 忽略或追踪文件或文件夹
在项目根目录下面 添加 .gitignore 文件。文件中每一行表示需要忽略的文件的正则表达式
忽略文件夹或文件:
-
/mtk/
过滤整个文件夹
-
*.zip
过滤所有.zip文件
-
js/*.zip
过滤js目录下所有.zip文件
-
/mtk/do.c
过滤某个具体文件
被过滤掉的文件就不会出现在git仓库中(gitlab或github)了,当然本地库中还有,只是push的时候不会上传。
追踪文件夹或文件:
与忽略唯一的区别就是规则开头多了一个感叹号,Git会将满足这类规则的文件添加到版本管理中。
-
!*.zip
追踪所有.zip文件
-
!/mtk/one.txt
追踪mtk目录下的 one.txt 文件
如果你不慎在创建
.gitignore
文件之前就push了项目,那么即使你在.gitignore
文件中写入新的过滤规则,这些规则也不会起作用,Git仍然会对所有文件进行版本管理。简单来说,出现这种问题的原因就是Git已经开始管理这些文件了,所以你无法再通过过滤规则过滤它们。因此一定要养成在项目开始就创建.gitignore文件的习惯,否则一旦push,处理起来会非常麻烦。
.gitignore
文件中的规则需要提交到 Git 仓库后才能生效。一旦你修改或添加了.gitignore
文件,你需要将这个文件提交到仓库,这样 Git 才会在以后的提交和状态检查中考虑这些规则。
2.4 忽略已经 push 到远程的文件
示例: /public/script/version.js 路径下的文件被 push 到了远程,直接在.gitignore 文件中添加规则 /public/script/version.js,push 到远程后发现并未生效。
原因:version.js
文件已经被纳入版本控制,那么 .gitignore
中的规则将不会起作用。你需要先从版本控制中移除该文件,然后提交更改。
git rm --cached public/script/version.js
git commit -m "Remove version.js from version control"
这样,文件将从版本控制中移除,而 .gitignore
中的规则将在以后生效。
3 提交及查看
3.1 初始化git仓储
在项目所在目录点击右键,选择 Git Bash Here, 输入 git init,会自动创建一个隐藏的空目录 .git,项目的备份代码会存储在这里
3.2 查看状态
git status
如当输入 git add ./文件名
后,可以通过它来查看文件是否放到了暂存区。 如果放到了入口,会显示:modified: readme.md
。
检测项目文件和存入仓储的文件是否一致,如果一致,返回 nothing to commit, working tree clean
。否则会显示红色字体的 modified: readme.md
。
3.3 将代码分两步存储到本地git仓储
-
把代码放到仓储暂存区
git add 文件名
将指定的文件放到暂存区
git add .
只要是修改过的文件都会放到仓储暂存区
-
把代码放到仓储房间
-
git commit -m 描述信息
git commit -m "这里写文件的描述信息" (m是message的简写)。如果没有写 -m,可以通过按ESC后输入 :q 来退出
-
3.4 查看日志(提交历史)
-
git log
可以查看到用户名,邮箱,每一次修改的时间和说明等内容。注意这是查看当前分支,再次按q退出
-
git log 分支名
查看指定分支的用户名,邮箱,每一次修改的时间和说明等内容。再次按q退出
-
git log --pretty=oneline
只显示提交的commitID 和 说明内容
-
git log --graph --all
--all 可以查看所有分支,已经被回退掉的分支也能查看到
-
git log --graph --pretty=oneline --abbrev-commit
查看分支合并情况
-
git blame
以列表方式查看指定文件的提交历史
3.5 查看文件修改内容
- git diff
4 撤消
4.1 用暂存区中的文件覆盖工作目录中的文件
git checkout 文件名
业务场景:代码写到一半的时候先把代码添加到了暂存区,继续写下面的代码,写完后发现代码有问题,要恢复到一半的时候,用这个命令就能把暂存区的代码覆盖本地的代码,从而实现回退
4.2 将文件从暂存区中删除
git rm --cached 文件名
业务场景:不小心把一些不需要上传到仓库的代码提交到了暂存区,可以用这个命令删除暂存区的文件,本地的文件不会受到影响
4.3 将文件从暂存区中删除
4.3 回退到之前的版本
根据commitID 回退到指定版本
git reset --hard commitID
将git仓库中指定的更新记录恢复出来,并且覆盖暂存区和工作目录
commitID: git log 命令可以获取到,commitID 格式:e6cc775bd2a738b0c22e6642794ddfcad2e7619a
通过 HEAD 回退到之前版本
git reset --hard HEAD^
HEAD表示当前版本,也就是最新的提交1094adb...,上一个版本就是HEAD^,上上一个版本就是HEAD^^,当然往上100个版本写100个^比较容易数不过来,所以写成HEAD~100
恢复回退之前的版本(穿梭至未来)
git reflog
记录你的每一次命令,这样可以查看到最近的操作,从而获取到 commitID,然后根据 ID 回退即可
5 把本地库的内容推送到远程
5.1 通过github中仓库中项目的http地址来推送
git push http地址 分支名
示例:git push origin github.com/wangjunjie0… master
注意:如果是用https的方式进行提交,第一次提交时需要输入github账号密码,后面就不需要了,这是win10 系统帮我记住了密码,不是git的功能。在控制面板-凭据管理器--windows凭据里面可以查看到
5.2 给远程提交增加别名
git remote add 别名 远程地址
示例:git remote add origin github.com/wangjunjie0…
然后就能通过 git push origin 分支名
来提交了,如提交到远程的 dev 分支可以这样写:git push origin dev。
5.3 查看远程仓库地址
git remote -v
5.4 远程仓库地址更改后本地仓库重新关联
git remote add 别名 远程地址
注意:此时若之前用 别名 origin 关联过了,现在仍然想用 origin 关联更改地址后的仓库,需要 <git remote rm 别名> 先删除关联过的别名再进行操作
5.5 记住远程仓库地址和分支名
git push -u origin master
-u 这样写是绑定origin和master的,下次推送只需要输入git push 就可以了
5.6 强制操作
强制提交
-
git push origin 分支名 --force
-
或 git push origin 分支名 -f
-
或 git push -f
会将远程文件覆盖,谨慎操作!
6 拉取操作
6.1 克隆远程仓库到本地(无本地仓库,相当于拷贝一份远程仓库)
-
git clone 远程地址
把远程仓库的内容克隆到执行git命令的文件夹,项目名称也就是远程仓库的名称 git clone github.com/wangjunjie0…
-
git clone <url> filename --depth=1
filename:克隆文件的重命名 --depth=1:只下载最后一次的commit(提交),其他历史记录不要
-
直接克隆远程指定分支
上面的命令默认克隆master主分支, 克隆远程指定分支可以用以下命令:
git clone -b <指定分支名> <远程仓库地址>
示例:git clone -b dev-permission github.com/wdlhao/vue2…
6.2 拉取远程仓库最新版本(本地仓库存在,远程仓库和本地仓库比较)
-
git pull 远程仓库地址 分支名
用地址和分支名的方式拉取。
-
git pull origin master
用别名的方式拉取远程代码,前提是给远程仓库添加过别名
-
git pull
拉取当前分支最新代码
6.3 强制拉取
-
git pull --rebase origin master
会将本地文件覆盖,谨慎操作!
7 将本地库内容推送到远程的完整步骤(远程仓库还未初始化的情况)
-
在本地项目中调出
git Bash here
-
命令行输入
git init
初始化git仓库 -
命令行输入
git add .
(将代码放到仓储暂存区) -
git commit -m '描述信息'
(将代码放到仓储房间) -
git remote add 别名 远程地址
给远程提交增加别名,一般会写成这样:
git remote add origin 远程地址
远程地址在github中复制。可以新建一个仓库 (注意:只是新建不要初始化这个仓库),然后在界面中复制地址就行了 -
然后就能通过
git push origin master
将代码提交到远程了或者根据
5.5节
方式记住远程仓库地址和分支名,下次推送只需要输入git push
就可以了
报错处理:
fatal: remote origin already exists.
这是因为之前已经关联过了,删除后再重新关联即可
git remote rm 别名
git remote add 别名 远程地址
8 分支
为了便于理解,大家暂时可以认为分支就是当前工作目录中代码的一份副本。使用分支,可以让我们从开发主线上分离出来,以免影响开发主线。
8.1 查看远程库信息
-
git remote
查看远程库的信息(简单信息), 返回远程仓库的名称,默认为 origin
-
git remote -v
查看远程库的信息(详细信息), 返回下方所示: origin http://192.168.3.95:10000/root/demo.git (fetch) origin http://192.168.3.95:10000/root/demo.git (push) 上方显示了可以抓取和推送的origin的地址。如果没有推送权限,就看不到push的地址
8.2 一般项目中所需分支
-
主分支(master)
第一次向git仓库中提交更新记录时自动产生的一个分支
-
开发分支(develop)
作为开发的分支,基于master分支创建
-
功能分支(feature)
作为开发具体功能的分支,基于开发分支创建
8.3 分支命令
-
git branch
显示所有本地分支
-
git branch -r
显示所有远程分支
-
git branch 分支名称(新写法:git switch -c 分支名称 )
创建分支,当前在哪个分支就基于哪个分支创建分支
-
git branch -m 指定分支名 新的分支名
重命名本地指定分支
-
git branch -m 新的分支名
重命名本地当前分支
-
重命名远程分支
先拉取想要重命名的最新远程分支,然后在本地重命名,然后删除远程分支,最后重新将重命名后的本地分支推送到远程即可
-
git branch -d 分支名称
删除本地分支,分支合并后才允许删除,将-d 换成 -D 为强制删除。
删除分支时需要切换到其他的分支,如果分支还没有合并 -d 不能删除,如有必要可以用 -D 强制删除
-
git push origin -d 分支名称
删除远程分支
-
git checkout 分支名称
(新写法:git switch 分支名称
)切换到指定分支。示例:创建并切换到dev分支:
git checkout -b dev(git switch -c dev)
在不同分支创建的文件提交后,切换到其他的分支是查看不到的,注意要提交,放到暂存区的不行。 如果不提交或不暂时保存更改就切换,会在其他分支上显示此分支新建的内容
-
git merge 来源分支
合并指定分支到当前分支,默认用 Fast forward(--ff) 模式合并。
如果当前分支上的工作已经完成,就可以把当前分支上的工作合并到其他分支上去了。 如需要把 develop 分支合并到 master,需要在 master 上操作
-
查看分支合并情况(简略版)
- git log --graph --pretty=oneline --abbrev-commit
图示:
-
查看分支合并情况(详细版)
- git log --graph
图示:
8.4 创建 及 切换分支图解
创建分支:Git新建了一个指针叫dev,指向master相同的提交,再把HEAD指向dev,表示当前分支在dev上
在分支工作:此时工作区的修改和提交就是针对dev分支了,比如新提交一次后,dev指针往前移动一步,而master指针不变
--ff 模式合并:直接把master指向dev的当前提交
删除dev分支:如果是 --ff 模式合并,删除分支后,会丢掉分支信息
8.5 本地分支与远程分支的关系维护篇
-
git branch -vv
查看本地分支和远程分支的映射关系
上图dev是本地分支,映射的是 origin/dev 远程分支
-
本地分支不存在dev,远程分支存在dev时的处理:
1、在本地创建dev分支:git switch -c dev
2、将本地分支关联到远程分支:git branch --set-upstream-to=origin/dev dev
解析:
git branch --set-upstream-to=origin/远程分支名 本地分支名
使用 git 在本地新建一个分支后,需要做远程分支关联。如果没有关联,git会在下面的操作中提示你添加关联。3、拉取远程分支到本地:git pull
-
本地分支存在 dev 远程分支不存在dev时的处理:
git push -u origin dev (git push -u origin 新建的远程分支名)
9 stash 暂时保存更改
适用于遇到临时的任务,可以在不提交分支任务的情况下切换分支。
-
git stash
存储临时改动到git的剪贴板
-
git stash save "save message"
执行存储时,添加备注,方便查找,只有git stash 也要可以的,但查找时不方便识别
-
git stash list
查看 临时改动到git的剪贴板
-
git stash pop
恢复改动,将git剪贴板上所有的改动恢复到分支上
-
git stash clear
删除所有缓存的stash
剪贴板是独立于分支之外的,所以在其他的分支也能执行这个命令,所以需要注意你当前所在的命令在哪个分支
10 标签管理
10.1 概述
标签其实它就是指向某个commit的指针(跟分支很像对不对?但是分支可以移动,标签不能移动),所以,创建和删除标签都是瞬间完成的。
那么有commit,为什么还要引入tag呢?tag就是一个让人容易记住的有意义的名字,它跟某个commit绑在一起,如tag指定为 v1.0.0 比 commitID 一串无意义额数字要好找
10.2 创建标签
-
在当前分支创建标签
git tag <tagname>
示例:
git tag v1.0
,默认标签是打在最新提交的 commit 上的。 -
在指定分支创建标签
git tag <标签名> commitID
示例:
git tag v0.9 f52c633
-
创建带有说明的标签
git tag -a 标签名 -m "说明文字" commitID
示例:
git tag -a v0.1 -m "version 0.1 released" 1094adb
用-a指定标签名,-m 指定说明文字,省略 commitID 时默认指定当前版本
-
查看所有标签
git tag
图示:
注意:标签不是按时间顺序列出,而是按字母排序的。可以用
git show <tagname>
查看标签信息
10.3 操作标签
-
删除
git tag -d <tagname>
示例:
git tag -d v0.1
,创建的标签都只存储在本地,不会自动推送到远程。所以,打错的标签可以在本地安全删除
-
推送某个标签到远程
git push origin <tagname>
示例:
git push origin v1.0
-
一次性推送全部尚未推送到远程的本地标签
git push origin --tags
-
删除远程标签
- 先从本地删除
git tag -d <tagname>
示例:
git tag -d v0.9
- 再从远程删除
git push origin :refs/tags/ <tagname>
示例:
git push origin :refs/tags/v0.9
10.4 真实场景再现
需求:本地只有 dev 分支无 master 分支,此时向远程 master 分支 push 内容并打上标签。
-
创建并切换到master分支
git switch -c master
-
拉取远程 master
git pull origin master --allow-unrelated-histories
-
将本地 master 分支映射到 远程 master
git branch --set-upstream-to=origin/master master
-
将本地 commit 推送到远程 master
git push -u origin master
-
创建带有说明的标签
git tag -a <标签名> -m "说明文字"
示例:
git tag -a v1.0 -m "xxx说明文字"
-
推送标签到远程master
git push origin v1.0
11 团队及跨团队协作(github为例)
11.1 团队协作
邀请合作者
-
只有仓库的所有者邀请合作者之后,合作者才能将代码提交到仓库。
-
在仓库中点击setting-collaborators,输入密码后,在输入框中输入被邀请者的github账号, 点击邀请后,上面会出现邀请链接,把这个链接发送给被邀请的程序员,被邀请进入这个链接接收邀请后就能向这个仓库提交代码了
11.2 跨团队协作
在其他开发者的github仓库中点击fork,此时会把这个仓库复制到自己的仓库中,先从自己仓库克隆到本地,然后可以在里面进行完善修改提交,修改完善完成可以发送给原开发者,如果采纳才能将你的代码合并到原作者的仓库。
以程序猿C为例的步骤:
-
程序猿C fork仓库
-
程序猿C 将仓库克隆在本地进行修改
-
程序猿C 将仓库推送到远程
-
程序猿C 发起 pull request
-
原仓库作者审核
-
原仓库作者合并代码
从自己仓库把修改后的代码向原作者发出请求的步骤
- 在自己本地仓库点击 Pull requests
- 点击New pull request
- 点击create pull request (在这一步可以写一些描述信息来和原作者进行沟通,然后修改信息就会发送给原作者了,原作者可以在自己仓库的Pull requests 中查看到这条信息,并予以回复)