基本印象
基本印象是最为重要的,因为我层四次学习git,但是最后都忘了.所以在一段时间后我能够记住多少知识才是我们的首要关注点.
基本印象就是保证我们记忆住最基本的只是,从而更快地重学习.
参考1:https://javabetter.cn/git/git-qiyuan.html
参考2:https://www.ruanyifeng.com/blog/2015/12/git-cheat-sheet.html
参考3:https://gitee.com/progit/index.html
参考3是git pro2
参考4:https://pdai.tech/md/devops/tool/tool-git.html
版本控制的几种方式
分布式版本控制和集中式版本控制
集中版本控制
相当于是主从复制,我们只有一个主服务器,要想要获取就只能从这一个服务器中获取,其他的都是slave不作数
优点就是没有冲突,缺点是必须联网保证和主服务器的网络通畅
分布式版本控制
在自己的电脑上搭建了版本仓库,这样就不需要联网了,也可以将自己的仓库推送到远程服务器上,这样实际上就可以让别人共享项目
优点就自己电脑本地就是一个仓库,当我们需要发送到远程服务器的时候才需要联网推送整个版本仓库
Git就是分布式版本控制系统
Git的基本模式
因为git就是分布式版本控制系统,所以git系统就有
- 远程仓库概念
- 本地仓库概念
最常用的就是本地仓库的使用了,而从本地仓库推送到远程仓库以及拉取远程仓库内容都比较简单
仓库的管理概念
向仓库中添加不同的版本,需要哪些步骤?
向仓库查询,获取不同的版本,需要怎么做?
解释
git提供了几种级别
- 当前工作版本桌面 Workspace
- 要存仓的版本袋子 Index/Stage
- 版本存放仓库 Repository
- 远程仓库 Remote
可以理解,我们操作修改workspace桌面上的东西,
改好以后装好放在袋子里,
等到所有东西都装在袋子里以后封袋存档
本地级别的基本使用
1 创建本地仓库
以目录为单位,在一个目录中创建仓库,这样Git就是将这个目录中的所有内容作为我们的软件的内容进行管理
实际的代码就是
然后当前目录会出现一个.git目录,里面保留了整个仓库的信息
还有两个命令也可以得到一个本地仓库
1 2 3 4 5
| # 新建一个目录,将其初始化为Git代码库 $ git init [project-name]
# 下载一个项目和它的整个代码历史 $ git clone [url]
|
2 编辑配置文件
git的配置文件叫做.gitconfig
配置文件分为两类
- 全局(Git)配置文件,位于用户主目录.gitconfig文件
- 项目(当前仓库)配置文件,位于项目目录下.gitconfig文件
配置文件主要就是一些用户配置,文件配置之类的
1 2 3 4 5 6 7 8 9
| # 显示当前的Git配置 $ git config --list
# 编辑Git配置文件 $ git config -e [--global] #也就是edit的缩写
# 设置提交代码时的用户信息 $ git config [--global] user.name "[name]" $ git config [--global] user.email "[email address]"
|
3 与暂存区的交互
记住,所以仅对本地目录,桌面的操作,都不需要用到git命令
所以只要是git命令操作一定影响stage或者repository或者remote
我们写好一个文件可以将文件保存到stage中
1 2 3 4 5 6
| # 添加文件到暂存区 git add [file1] [file2] ... # 添加目录到暂存区 git add [dir] # 添加当前所有到暂存区 git add . # 或者git add ./* ,git对于linux语法很支持
|
如果暂存区有一个相同文件名的存在,那么git会进行询问
如果你并不是向整个覆盖,那么你可以使用更小粒度的更新,这样git会在每一处修改处问你是否要覆盖?
1 2 3
| # # 添加每个变化前,都会要求确认 # 对于同一个文件的多处变化,可以实现分次提交 git add -p [同名文件]
|
也可以删除袋子中的文件
1 2 3 4 5 6
| # 删除桌面上的文件,!同时!删除袋子中的 git rm [file1] [file2]... # 也可以只删除袋子中的,这样桌面上的还保留,可以通过git add继续装袋 git rm --cache [file]... # 当然可以直接把工作目录的文件删除了 rm file # linux指令
|
元信息修改
例如文件改名
1 2
| # 改名!同时!提交到缓存区 git mv [old_filename] [new_filename]
|
如果我们直接在工作区给文件改名,那么git将不认得这个文件,会显示成untracked的新文件
4 与本地仓库的交互
提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| # 将整个袋子存档到仓库,必须有版本信息哦 git commit -m'版本信息' # 将某些文件单独存档到仓库 git commit [file1][file2] -m'版本信息' # 直接工作区提交到仓库 git commit -a # 也就是-all的意思 # 提交的时候显示版本差异 git commit -v #也就是带上-v就可以
# 也许你提交失误了,你可以覆盖上次的提交 git commit --amend -m'message'
# 也许你不想完全覆盖上次提交,只想修改一些文件 git commit --amend [file1][file2]...
|
本质理解
如果我们真的想理解这些命令的效果,我们必须知道git的工作原理
基本理解
本质1 Git以文件为版本单位
其他的版本控制系统,是发现与上一次提交文件的变化,然后记录文件变化,我们想要获取某次的文件版本就需要从初始文件,然后读取修改才能获得
Git是计算此次提交文件整体的hash值,如果不同就保存为一个新的文件版本,这个文件保存了完整的文件内容,如果和之前的文件版本相同,git就会创建一个指向该文件的链接占位
所以,Git的粒度更大,保存最小单位为是一个文件,而其他的控制系统最小是文件中的一次修改
所以我们要以文件作为版本控制的基本视野

如上图,我们的项目里面有A,B,C三个文件
如果新的提交和之前的提交没有差异,就会指向之前的文件版本.
如果有差异就会直接保存文件作为一个新的版本
本质2 git发现差异的原理
git实际上会将文件的全部内容进行内容校验和运算,最后得到SHA-1 算法计算数据的校验和
git通过这个值,来比较文件是否相同.
Git 的工作完全依赖于这类指纹字串,所以你会经常看到这样的哈希值。实际上,所有保存在 Git 数据库中的东西都是用此哈希值来作索引的,而不是靠文件名。
git diff 检查工作区和暂存区中文件的不同
本质3 文件的四种状态
在git中,文件只有三种状态
- 已提交 committed
- 已修改 modified
- 已暂存 staged
- 未追踪 untracked
我们需要理解追踪的意思
文件追踪
我们知道git中的版本控制是以文件为单位的
所以git中最常见的操作就是修改文件中的内容,这样git就会保存新版本的文件的快照
所以我们更新的文件,也就是git知道的文件,有上一个版本的文件就被叫做 tracked文件
如果我们添加一个新的文件,git完全不知道,所以就显示叫做 untracked文件
基本的工作流程如下:
- 在工作目录修改了某些文件
- 将文件保存到缓存区
- 提交更新,将保存在暂存区的文件快照保存在Git目录中
使用基础
使用git之前我们需要知道一些基础东西
一个是配置,一个是帮助
三个地方:
- /etc/gitconfig 全局配置 优先级最低
- ~/.gitconfig 当前用户配置 优先级中等
- .git/config 当前项目配置 优先级最高
包括下面的配置
配置用户信息
我们在提交的时候,git需要记录这次提交的用户信息,所以我们需要配置
通过git config --global user.name 你的用户名
进行配置
以及用户的emailgit config --global user.email 你的邮箱
获取帮助
另一个基础是获取git的帮助
没人能永远记住所有的git指令,当我们有疑问的时候,调用git帮助是最快的解决方法
- git help
<verb>
- git
<verb>
–help
- man git -
<verb>
这三种方式都可以查看一个命令的帮助
新手开始
首先我们创建一个git 项目,git会将这个目录作为工作区,可以追踪工作区中的所有文件(默认排除.git文件夹因为这个文件夹就是git的仓库)
1 2 3 4 5 6
| # 我们可以自己初始化一个项目 git init # 或者我们可以下载一个git项目 git clone [url]
|
查看文件状态
我们知道文件有四种状态,我们可以查看工作区中文件的状态
可能有几种情况
- untracked 有一些未追踪的新文件
- deleted 删除了一些文件
- modified 修改了一些文件的内容
跟踪新的文件
通过git add [file]
来将文件加入暂存区
高级使用
当我们真的想使用git的时候我们就需要了解这部分的知识,因为了解了才能够方便的进行版本的管理
分支管理
同一个版本做出不同的修改,那么就会衍生出不同的版本分支,这些分支都来自同一个版本,但是却都是不同的版本
这里的分支可以来源于其他分支,也可以独成一派
合并分支,相当于就是将下一个版本指向另外的分支版本,例如将开发分支合并到master分支,这样相当于是发布为正式版


查看分支
1 2 3 4 5 6 7 8
| # 查看本地分支 git branch
# 查看远程分支 git branch -r #也就是remote的缩写
# 查看所有分支(本地以及远程) git branch -a
|
新建分支
1 2 3 4 5 6 7 8 9 10 11
| # 新建一个分支,来自当前分支的最新提交版本,但是不切换分支 git branch [branch-name]
# 新建一个分支来自当前版本,然后切换到该分支 git checkout -b [new-branch] # 实际上切换分支的命令就是git checkout [branch-name]
# 新建分支,然后指向某个版本 git branch [new-branch][commit]
# 新建分支,并作为远程分支的代表 git branch --track [new_branch][remote_branch]
|
切换,合并分支
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| # 切换分支并且,更新工作区 git checkout [branch] #所以注意,保存你的工作区,否则就要丢失了
# 切换到上一个分支 git checkout - #记得linux中cd -就是回到上一次的目录
# 建立追踪关系,在已有分支和远程分支之间 git branch --set-upstream [branch] [remote_branch]
# 合并指定分支到当前分支 git merge [branch]
# 选择一个commit 合并进入当前分支, git cherry-pick [commit]
|
删除分支
1 2 3 4 5 6 7
| # 删除分支 git branch -d [branch-name]
#删除远程分支 git push origin --delete [branch-name] git branch -dr [remote-branch]
|
标签管理
标签是什么?实际上就是给我们版本添加一个快捷方式,添加了描述以及快速选择。
**标签实际上就是commit的别名,**在命令上都可以代替commit出现
显示标签
添加标签
1 2 3 4 5 6
| # 给当前版本添加一个标签 git tag [tag_name]
# 给指定版本加上标签 git tag [tag_name] [commit]
|
删除标签
1 2 3 4 5 6
| # 删除指定标签 git tag -d [tag_name]
# 删除远程标签 git push origin :refs/tags/[tag_name] # 实际上用到的是底层命令
|
查看标签信息
实际上就是查看标签所在的版本的信息
1 2
| # 查看信息 git show [tag_name] # 也就相当于是标签是commit的别名
|
提交到远程仓库
1 2 3 4 5
| # 实际上就是push命令中,使用标签代替commit的位置 git push [remote] [tag]
# 提交所有的tag git push [remote] --tags
|
远程操作(remote操作)
我们操作远程仓库
显示远程仓库
1 2 3 4 5 6
| # 显示所有的远程仓库 git remote -v #意思就是-v visiable可视的意思
# 显示某个具体的远程仓库的信息 git remote show [remote]
|
添加远程仓库
1 2
| # 给项目添加一个远程仓库 git remote add [shortname] [url]
|
从远程仓库获取内容
1 2 3 4 5 6
| # 下载所有的变动 git fetch [remote]
# 下载最新版本并合并到本地分支 git pull [remote][branch]
|
上传到远程
1 2 3 4 5 6 7 8
| # 上传本地指定分支 git push [remote] [branch]
# 上传当前当前分支,强制覆盖 git push [remote] --force
# 推送所有分支到远程, git push [remote] --all
|
本地操作
获取到工作区 checkout
1 2 3 4 5 6 7 8
| # 从stage读取到工作区 git checkout [file] # 实际上的意思就是切换到版本
# 从commit中读取到工作区,以及暂存区 git checkout [commit/tag] [file]
# 从stage中读取所有到工作区 git checkout .
|
所以可以知道,默认都是从暂存区回退到工作区的,想要从仓库回退,必须指明仓库的版本
获取到暂存区 reset
1 2 3 4 5 6 7
| # 从当前commit中获取到暂存区,但是工作区没影响 git reset [file] # 从当前commit中获取到暂存区 git reset [commit]
# 包括工作区一起重置(容易丢失工作区修改) git reset --hard git reset --hard [commit/tag]
|
改变commit
1 2 3 4 5 6 7 8 9 10
| # 重置当前HEAD为指定commit,但保持暂存区和工作区不变 $ git reset --keep [commit]
# 新建一个commit,用来撤销指定commit # 后者的所有变化都将被前者抵消,并且应用到当前分支 $ git revert [commit]
# 暂时将未提交的变化移除,稍后再移入 $ git stash $ git stash pop
|
发布版本
1 2
| # 将项目打包成一个可发布的压缩包 git archive
|
查看信息
非常常用的命令类型
git status 系列
用来显示当前工作区,暂存区,仓库中的状态,差异之类的
1 2
| # 显示当前工作区,暂存区,仓库版本的状态 git status
|
git log 系列
显示当先版本的日志,包括commit编号,提交时间,作者,分支,标签之类的信息
1 2 3 4 5 6 7 8
| # 显示当前版本日志 git log
# 显示commit日志和详情(内容有哪些修改) git log --stat
# 搜索提交例如,根据关键词 git log -S [search_keys]
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61
| # 显示有变更的文件 $ git status
# 显示当前分支的版本历史 $ git log
# 显示commit历史,以及每次commit发生变更的文件 $ git log --stat
# 搜索提交历史,根据关键词 $ git log -S [keyword]
# 显示某个commit之后的所有变动,每个commit占据一行 $ git log [tag] HEAD --pretty=format:%s
# 显示某个commit之后的所有变动,其"提交说明"必须符合搜索条件 $ git log [tag] HEAD --grep feature
# 显示某个文件的版本历史,包括文件改名 $ git log --follow [file] $ git whatchanged [file]
# 显示指定文件相关的每一次diff $ git log -p [file]
# 显示过去5次提交 $ git log -5 --pretty --oneline
# 显示所有提交过的用户,按提交次数排序 $ git shortlog -sn
# 显示指定文件是什么人在什么时间修改过 $ git blame [file]
# 显示暂存区和工作区的差异 $ git diff
# 显示暂存区和上一个commit的差异 $ git diff --cached [file]
# 显示工作区与当前分支最新commit之间的差异 $ git diff HEAD
# 显示两次提交之间的差异 $ git diff [first-branch]...[second-branch]
# 显示今天你写了多少行代码 $ git diff --shortstat "@{0 day ago}"
# 显示某次提交的元数据和内容变化 $ git show [commit]
# 显示某次提交发生变化的文件 $ git show --name-only [commit]
# 显示某次提交时,某个文件的内容 $ git show [commit]:[filename]
# 显示当前分支的最近几次提交 $ git reflog
|
其他概念
例如远程仓库
一些配置
- git将中文显示为八进制字符编码问题
将git配置文件 core.quotepath
项设置为false
。quotepath
表示引用路径,加上--global
表示全局配置
git bash
终端输入命令:
1
| git config --global core.quotepath false
|
- git自动转换换行符的问题
1 2 3 4 5 6
| // 提交时转换为LF,检出时转换为CRLF git config --global core.autocrlf true // 提交时转换为LF,检出时不转换 git config --global core.autocrlf input // 提交检出均不转换 git config --global core.autocrlf false
|
1 2 3 4 5 6
| // 拒绝提交包含混合换行符的文件 git config --global core.safecrlf true // 允许提交包含混合换行符的文件 git config --global core.safecrlf false // 提交包含混合换行符的文件时给出警告 git config --global core.safecrlf warn
|