git | 常用操作和命令
唠唠闲话
Git 是目前世界上最先进的分布式版本控制系统,可以用于敏捷高效地处理任何或小或大的项目。所谓“分布式”是因为它的代码库可以同时存在于多个计算机上,并且这些代码库之间可以相互同步和交换代码更新。每个开发者都可以在本地拥有一份完整的代码库,可以独立地进行代码修改和提交,然后将这些修改推送到共享的远程仓库中。这种去中心化的代码管理方式,使得团队成员可以更灵活地协作,不受网络限制,在断网情况下也能继续工作。
个人而言,主要用 Git 实现这些功能:
- 备份,同步本地项目
- 多设备管理项目
- 文件历史版本(改错的后悔药)
- 管理 GitHub 项目
- 部署博客网站
本篇记录 Git 中经常用的操作和命令,方便查阅,至于 Git 的安装和工作原理网上有大把介绍,就没必要赘述了。
推荐网站:廖学锋的 Git 教程,最开始学习 Git 就在这个网站。
推荐书籍:高见龙的 《Git 从入门到精通》
基本操作
修改配置
-
用
git commit
提交修改时,需要“自报家门”,也就是提交人的姓名和邮箱,命令如下:1
2
3
4
5
6
7
8
9
10
11# 设置用户名和邮箱
git config --global user.name "Your Name"
git config --global user.email "email@example.com"
# 查看用户名和邮箱
git config --global user.name
git config --global user.email
# 取消用户名和邮箱
git config --global --unset user.name
git config --global --unset user.email -
补充说明
--global
参数全局设置用户名和邮箱- 在 git 仓库中,不加
--global
或者改用--local
参数,则给仓库单独设置用户名和邮箱 - 用户名和邮箱的双引号
""
可写可不写
-
git 默认编译器为 vim,可更换编译器为 vscode
1
git config --global core.editor "code --wait"
注意参数
--wait
表示等待文本的编辑关闭,否则每次立即返回空commit
,导致提交失败。 -
使用
git config --list
查看整体设置
在 git 仓库下,使用git config --list
可以查看更多信息
-
git 的全局配置为主目录的
.gitconfig
文件,可直接编辑修改 -
在 git 中,通过
alias.<缩写>
可设置命令缩写,比如单行显示历史1
2
3
4
5
6# 完整输入
git log --pretty=oneline
# 设置简写
git config --global alias.pretty "log --pretty=oneline"
# 简写输入
git pretty -
常用的几个命令缩写
1
2
3
4
5
6
7# 撤销工作区的更改
git config --global alias.discard "restore --staged ."
# 修改最后一次提交
git config --global alias.amend "commit --amend --no-edit"
# 打印简写
git config --global alias.pretty "log --pretty=oneline"
git config --global alias.oneline "log --oneline"
新建,添加,提交
-
在目标文件夹下,输入命令,新建仓库
1
git init
-
git add
将工作区的文件提交到暂存区,常见用法:1
2
3
4
5git add <文件路径> # 添加文件
git add <文件夹路径> # 添加文件夹
git add *.html # 使用正则表达式匹配和添加文件
git add . # 添加当前目录的文件和改动
git add --all # 添加所有文件和改动补充说明:
git add
只能添加仓库所在文件夹内的文件git add -p <文件名>
可以只提交文件的部分内容
-
git commit
将暂存区的文件提交到版本库,常见用法:1
2
3
4
5
6
7
8
9# 单行注释
git commit -m "<注释>"
# 使用文本编辑器编写注释,默认编辑器为 vim
git commit
# 提交空内容:常用于演示,实战项目不建议使用
git commit --allow-empty -m "empty commit"
# -a 参数,直接将暂存区的所有改动提交到版本库
git commit -a -m "don't need git add"
git commit -am "don't need git add"补充说明:
- git 要求每次提交都必须填写修改信息,原则上,信息内容应尽可能简单,清楚
git commit -a
提交工作区时,只能添加已追踪的文件,新文件无法处理
-
git status
查看当前工作区状态
查看历史信息
-
直接输入
git log
显示提交历史的详细信息1
git log
-
三种版本历史的简洁显示方式,可配合
git config alias
设置缩写1
2
3git log --pretty=oneline
git log --oneline
git log --oneline --graph -
git 许多操作需要指定版本,两种常用方式分别是
commit-id
和HEAD
。commit-id
就是图中的橙色字体,一串 SHA1 码。指定某个版本,只需输入commit-id
的前几位数字(至少4位),并确保不出现歧义。HEAD
用法如下:HEAD
表示当前最新版本HEAD^
表示前一版本,多个^
代表前几个HEAD~n
表示前 n 个版本,n 取 0 代表最新版本。
-
技巧1-根据提交信息检索特定 commit
1
2
3
4
5
6# 检索作者
git log --oneline --author="rex"
# 使用转义 \| 表示或运算
git log --oneline --author="rex\|wang"
# 检索关键字
git log --oneline --grep="1.txt" -
技巧2-根据提交时间或文本内容,检索特定 commit
1
2
3
4
5
6
7# 版本历史中检索涉及关键字内容的版本
git log -S "txt change"
# 查找某一时段的 commit
# 查找今天某一时段的改动
git log --oneline --since="9am" --until="12am"
# 查找某天开始,每天某一时段的改动
git log --oneline --since="9am" --until="12am" --after="2022-01-01" -
技巧3-检索设计特定文件的 commit,追加参数
-p
可以查看具体修改1
git log --oneline <文件名>
-
“这行代码是谁写的!” 用
git blame <文件名>
查看某个文件的某一行代码是谁提交的,比如
前 5 行由两个 commit-id 修改,去掉参数--oneline
可以看具体提交用户是谁。
删除,变更文件
-
删除文件,并将修改添加到暂存区
1
2
3
4git rm <文件>
# 相当于
rm <待删除文件>
git add <删除的文件> -
如果只是取消文件的追踪,可以用
--cached
参数,删除暂存区的文件,而保留工作区原先的文件1
git rm <取消追踪的文件> --cached
注:这个方法常用于删除被
.gitignore
添加,却仍在暂存区的文件 -
移动并将修改添加到暂存区
1
2
3
4git mv <file1> <file2>
# 相当于
mv file1 file2
git add file1 file2
amend 修改最后一次提交
下边介绍 --amend
参数的方法。
-
场景一:当
commit
信息填写不当,需要改动时,有以下几种方法:git reset
版本回退,再重新提交 commit- 使用
git rebase
命令(后边单独介绍) - 使用
--amend
参数,改动最后一次的 commit
-
举个例子,commit 时手滑写了
WTF
,赶紧用--amend
修改提交信息1
2git log --oneline
git commit --amend -m "Welcome To Facebook" -
场景二:刚刚完成一次
commit
,但发现一些细节没有改好,又不想为这些细节重新发一次 commit,这是有几种方法:git reset --soft/--mixed
版本回退,添加修改再重新提交- 使用
--amend
修改最后一次的 commit
-
举个例子
1
2
3# < 文件改动 >
# git add ... 添加文件到暂存区
git commit --amend --no-edit # 提交修改最后的参数
--no-edit
表示无需修改提交信息,也可以用信息替代
gitignore
参考链接
CSDN:Git 中使用 .gitignore
CSDN:.gitignore 失效解决方法
-
git 仓库中,
.gitignore
指定的文件和文件夹会被git add
自动忽略,但-f
参数可以让git add
添加被忽略的文件。
使用说明:<文件/文件夹>
忽略所有目录下的该文件或文件夹./<文件/文件夹>
忽略当前目录下的该文件名或文件夹! <文件/文件夹
!
代表取消忽略
-
如果文件夹被
.gitignore
忽略,用git add <path> -f
强制添加后,只有添加时刻的文件被 git 记录,之后文件夹内的其他文件变化都不会被记录。 -
注意,
.gitignore
文件本身也可以设置被忽略,但使用场景很少。假设我需要在不同设备上,使用不同的.gitignore
,那么我在每个设备上,都添加.gitignore
,并忽略文件自身。这样一来相应文件可以设置忽略,而.gitignore
也不会被共享。 -
使用命令
git clean -fX
清除被忽略的文件,其中参数-f
指强制删除。
版本库相关
初学 Git 必须掌握的三个概念: 工作区
,缓存区
和 版本库
。
查看改动
参考链接
简书:Git diff 比较两个版本文件之间的差异
博客园:git 还原文件到之前版本
假设某个文件修改后出 bug,我们需要将文件和以前版本对比,找出问题,这时用 git diff
来完成。语法如下,方括号 []
内的参数可选,默认查看整个工作区。
1 | # 工作区和暂存区的差异 |
图片示例
回退文件
文件不小心改错,要回退到改错前的版本,有两种方法
-
git checkout
回退文件1
2
3git checkout <commit-id> <filename> # 将文件回退到 commit-id 的版本
git checkout <filename> # 将文件回退到 HEAD 版本
git checkout . # 将当前目录回退到 HEAD 版本注:
git checkout
同时回退工作区和暂存区的文件,因而不需要再用git add
-
git resotre
回退文件1
2git restore --staged <文件> # 暂存区文件回退 HEAD 状态
git restore <文件> # 文件回退为 HEAD 状态,与 git checkout 等效添加参数 --staged 可以只回退暂存区的文件
回退工作区
git reset
版本回退,本质上是修改 HEAD 指向的位置。有三个可选参数 soft
, hard
和 mixed
,不同参数对工作区和暂存区有不同影响,默认参数为 mixed
,参考这里。
三者区别如下:
-
git reset --soft
保留 工作区和暂存区 的内容,简单来说就是你的代码还在只是变成了未提交状态或未添加状态
-
git reset --hard
回退 工作区和暂存区 到指定的 commit 版本
-
git reset --mixed
保留 工作区 的内容,回退 暂存区 到指定的 commit 版本
git 分支
分支是 git 最重要的功能之一,特别是团队项目,而一些个人使用场景中,Git 分支也能发挥很大作用。
基本操作
1 | git branch # 查看分支 |
当远程存在某一分支,而本地未同步时,可以用 switch
命令,将在本地创建相应分支
1 | git switch <分支名> |
常用命令的分支操作
1 | git clone -b <dev> <github 地址> # 克隆远程仓库的指定分支 dev |
删除分支
参考博客园: Git删除分支/恢复分支
-
如果需要删除的分支不是当前正在打开的分支,使用
branch -d
直接删除1
git branch -d <branch_name>
-
删除一个正打开,或未合并的分支,需使用 -D 选项
1
git branch -D <branch_name>
-
删除远端分支
1
git push origin --delete <分支名>
恢复被删除的分支
Git 会自行负责分支的管理,所以当我们删除一个分支时,Git 只是删除了指向相关提交的指针,但该提交对象依然会留在版本库中。因此,如果我们知道删除分支时的散列值,就可以将某个删除的分支恢复过来。在已知提交的散列值的情况下恢复某个分支:
1 | git branch <branch_name> <hash_val> |
如果我们不知道想要恢复的分支的散列值,可以用 git reflog
命令将它找出来。例如:
- 删除分支
- 输入
git branch next HEAD@{1}
恢复分支。
!pic
注:
git reflog
命令显示整个本地仓储的 commit,包括所有 branch 的 commit ,甚至包括已经撤销的 commit。只要 HEAD 发生了变化, 就会在 reflog 里面看得到。
Github
GitHub 是世界上最大的同性交友网站基于 Git 的一个代码托管网站。开发者可以将代码在 GitHub 上开源,可以浏览其它项目的代码,fork
到自己名下做修改,clone
回本地(没有访问权限的 private repo 除外)使用,也可以发起 pull request
向上游提交自己的修改。
本节整理 Github 中常见场景的 Git 使用方法,初次使用 Github 还要进行设置:GitHub | 多账户设置以及下载加速。
注:基于 Git 的代码托管网站还有很多,比如
Gitlab
,Gitee(码云)
等等,但相比之下,Github 有更多的生态基础。引用 Coding 的一段精炼介绍:Github 发明了碉堡了的两个功能:Fork
和Pull Request
。这两个功能创造了整个 Github 生态系统,使得“基因”得以繁衍和进化,充满了生命力。基因通过Fork
被复制,而Pull Request
使得基因得以进化。好的基因会被大量的Fork
,从而实现了优胜劣汰。这一整套体系才是精华所在,说 Github 是代码仓库显然太肤浅了。
本地推送到云端
- 在远端新建仓库
git remote
连接远端仓库1
git remote add origin <git 仓库地址> # 添加远端仓库为分支 origin
- 将本地仓库推送到远端
1
git push -u origin master
注:
-u
参数设置默认推送的分支,后续推送本地修改只需要git push
。
远端克隆到本地
- 复制远端仓库地址
git clone
到本地,此时目录下多了相应 git 仓库1
git clone <git 仓库地址>
- 如果对克隆的仓库有修改权限,后续可用
git push
推送本地修改
修改连接的仓库
使用场景:
- 远端仓库改名了
- 准备推送到另一个 github 仓库,或另一个平台的仓库
- 用 Gitee 给 git clone 加速
-
取消当前仓库的链接
1
2
3git remote # 查看远端仓库的分支名
git remote -v # 查看远端仓库链接
git remote remove origin # 删除远端分支 -
连接新仓库,并推送本地内容
1
2git remote add origin <git 仓库地址>
git push -u origin master
其他事项
汇总 Git 使用过程中遇到的问题。
未跟踪文件
没有被 git 跟踪的文件,不受 git 命令影响。
例如被 .gitignore
忽略的文件,或者尚未被 git add
的文件。无论用 git reset
重置工作区,git checkout
切换分支,还是 git rm * -rf
清空文件,都不影响。
win 换行符
参考 CSDN
在 windows 平台下 git add 的时候经常会出现如下错误
问题原因:
git 在 windows 下,默认是 CRLF 作为换行符,git add
提交时,检查文本中有 LF 换行符( linux 系统里面的),则会警告。所以问题的解决很简单,让 git 忽略该检查即可。
解决方法:执行下边命令
1 | git config --global core.autocrlf false |
fetch 和 pull
git fetch
和 git pull
命令的区别:
-
git fetch
: 从远程仓库中获取最新的代码更新,并将其保存到本地的版本库中。这些更新不会立即应用到你当前的分支中,而是需要手动合并(merge)到本地分支后才能看到更改。在这个过程中,远程仓库中的更改被下载到本地版本库的远程跟踪分支(如 origin/master),而不会影响工作区或暂存区。 -
git pull
:从远程仓库获取最新的代码更新,并自动将其合并到你当前的分支中。它实际上是执行了git fetch
和git merge
的组合操作。具体来说,git pull
将远程仓库中的更改下载到本地版本库的远程跟踪分支,然后将这些更改与当前分支进行合并。如果当前分支有未提交的修改,那么git pull
会先自动将这些修改提交到本地版本库中,再进行合并。