Git基础
Git基础
工作中使用 Git进行项目管理是一种非常常见的方式,那么学习 Git相关的知识就非常有必要了。在写这篇笔记的时候我只会几个很简单的几个命令(clone、pull、add、commit、push),对于 git如何创建分支,合并分支,以及解决冲突的方案。还有一些 Git插件和工具的使用是一概不知。
学习目标
- 掌握安装和cli的基本使用
- 掌握一个项目从初始化到提交到远程仓库的流程
- 掌握 git 分支的使用
- 掌握 git 历史版本查看和回退
- 掌握使用 git 时经常会遇到的问题
安装 git
略,这个没啥说的。遇到安装问题直接百度吧
在 Linux 上安装
在 Macos 上安装
在 Windows 上安装
从源代码安装
初次运行git时的配置
Git 自带一个 git config 的工具来帮助设置控制 Git 外观和行为的配置变量。 这些变量存储在三个不同的位置:
在Linux环境下:
/etc/gitconfig文件: 包含系统上每一个用户及他们仓库的通用配置。 如果在执行git config时带上--system选项,那么它就会读写该文件中的配置变量。 (由于它是系统配置文件,因此你需要管理员或超级用户权限来修改它。)~/.gitconfig或~/.config/git/config文件:只针对当前用户。 你可以传递--global选项让 Git 读写此文件,这会对你系统上 所有 的仓库生效。- 当前使用仓库的 Git 目录中的
config文件(即.git/config):针对该仓库。 你可以传递--local选项让 Git 强制读写此文件,虽然默认情况下用的就是它。 (当然,你需要进入某个 Git 仓库中才能让该选项生效。)
在Windows环境下:
存储在 用户目录下
你可以通过以下命令查看所有的配置以及它们所在的文件:
C:\Users\19878>git config --list --show-origin
file:D:/CodeApplication/Git/Git/etc/gitconfig diff.astextplain.textconv=astextplain
file:D:/CodeApplication/Git/Git/etc/gitconfig filter.lfs.clean=git-lfs clean -- %f
file:D:/CodeApplication/Git/Git/etc/gitconfig filter.lfs.smudge=git-lfs smudge -- %f
file:D:/CodeApplication/Git/Git/etc/gitconfig filter.lfs.process=git-lfs filter-process
file:D:/CodeApplication/Git/Git/etc/gitconfig filter.lfs.required=true
file:D:/CodeApplication/Git/Git/etc/gitconfig http.sslbackend=openssl
file:D:/CodeApplication/Git/Git/etc/gitconfig http.sslcainfo=D:/CodeApplication/Git/Git/mingw64/etc/ssl/certs/ca-bundle.crt
file:D:/CodeApplication/Git/Git/etc/gitconfig core.autocrlf=true
file:D:/CodeApplication/Git/Git/etc/gitconfig core.fscache=true
file:D:/CodeApplication/Git/Git/etc/gitconfig core.symlinks=false
file:D:/CodeApplication/Git/Git/etc/gitconfig pull.rebase=false
file:D:/CodeApplication/Git/Git/etc/gitconfig credential.helper=manager
file:D:/CodeApplication/Git/Git/etc/gitconfig credential.https://dev.azure.com.usehttppath=true
file:D:/CodeApplication/Git/Git/etc/gitconfig init.defaultbranch=master
file:C:/Users/19878/.gitconfig user.name=wukai198786
file:C:/Users/19878/.gitconfig user.email=1987860384@qq.com
file:C:/Users/19878/.gitconfig credential.https://gitee.com.provider=generic
file:C:/Users/19878/.gitconfig filter.lfs.clean=git-lfs clean -- %f
file:C:/Users/19878/.gitconfig filter.lfs.smudge=git-lfs smudge -- %f
file:C:/Users/19878/.gitconfig filter.lfs.process=git-lfs filter-process
file:C:/Users/19878/.gitconfig filter.lfs.required=true
修改用户信息
安装完 Git 之后,要做的第一件事就是设置你的用户名和邮件地址。 这一点很重要,因为每一个 Git 提交都会使用这些信息,它们会写入到你的每一次提交中,不可更改:
git config --global user.name "John Doe"
git config --global user.email johndoe@example.com
--global参数表示全局设置,如果希望指定特定项目,在项目内不加 --global参数即可
设置文本编辑器
既然用户信息已经设置完毕,你可以配置默认文本编辑器了,当 Git 需要你输入信息时会调用它。 如果未配置,Git 会使用操作系统默认的文本编辑器。
这里在 Windows 系统下这只 notepad ++ 为例
git config --global core.editor "'C:/Program Files/Notepad++/notepad++.exe' -multiInst -notabbar -nosession -noPlugin"
目前我还没有用到这个东西,等实际用到了再看
检查配置信息
如果想要检查你的配置,可以使用 git config --list 命令来列出所有 Git 当时能找到的配置:
C:\Users\19878>git config --list
diff.astextplain.textconv=astextplain
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
http.sslbackend=openssl
http.sslcainfo=D:/CodeApplication/Git/Git/mingw64/etc/ssl/certs/ca-bundle.crt
core.autocrlf=true
core.fscache=true
core.symlinks=false
pull.rebase=false
credential.helper=manager
credential.https://dev.azure.com.usehttppath=true
init.defaultbranch=master
user.name=wukai198786
user.email=1987860384@qq.com
credential.https://gitee.com.provider=generic
filter.lfs.clean=git-lfs clean -- %f
filter.lfs.smudge=git-lfs smudge -- %f
filter.lfs.process=git-lfs filter-process
filter.lfs.required=true
你可能会看到重复的变量名,因为 Git 会从不同的文件中读取同一个配置(例如:/etc/gitconfig 与 ~/.gitconfig)。 这种情况下,Git 会使用它找到的每一个变量的最后一个配置。(这个目前感觉没用到)
git config user.name
获取帮助
若你使用 Git 时需要获取帮助,有三种等价的方法可以找到 Git 命令的综合手册(manpage):
$ git help <verb>
$ git <verb> --help
$ man git-<verb>
例如,如果你想了解 git clone 命令的用法,你可以运行 git help clone。命令行会显示关于 git clone 的详细说明和用法。
例如,要想获得 git config 命令的手册,执行
git help config
但实际上,要是真遇到问题,还是得百度。毕竟很基础的命令也不需要看手册。而且这个手册是英文的,我根本看不懂。
git基础
获取仓库
通常有两种获取 Git 项目仓库的方式:
- 将尚未进行版本控制的本地目录转换为 Git 仓库;
- 从其它服务器 克隆 一个已存在的 Git 仓库。
两种方式都会在你的本地机器上得到一个工作就绪的 Git 仓库。
在已存在目录中初始化仓库
如果你有一个尚未进行版本控制的项目目录,想要用 Git 来控制它,那么首先需要进入该项目目录中。 如果你还没这样做过,那么不同系统上的做法有些不同:
先进入项目根目录,之后执行:
该命令将创建一个名为 .git 的子目录,这个子目录含有你初始化的 Git 仓库中所有的必须文件,这些文件是 Git 仓库的骨干。 但是,在这个时候,我们仅仅是做了一个初始化的操作,你的项目里的文件还没有被跟踪。
如果在一个已存在文件的文件夹(而非空文件夹)中进行版本控制,你应该开始追踪这些文件并进行初始提交。 可以通过 git add 命令来指定所需的文件来进行追踪,然后执行 git commit :
git add *.c
git add LICENSE
git commit -m 'initial project version'
克隆现有仓库
克隆仓库的命令是 git clone <url> 。 比如,要克隆 Git 的链接库 libgit2,可以用下面的命令:
git clone https://github.com/libgit2/libgit2
如果你想在克隆远程仓库的时候,自定义本地仓库的名字,你可以通过额外的参数指定新的目录名:
git clone https://github.com/libgit2/libgit2 my-project-name
文件状态
文件状态有两种 已跟踪和 未跟踪。
检查文件状态
可以用 git status 命令查看哪些文件处于什么状态。 如果在克隆仓库后立即使用此命令,会看到类似这样的输出:
C:\Users\19878\Desktop\git-test\my-app>git status
On branch master
nothing to commit, working tree clean
如果新建或者修改了文件会提示如下:
C:\Users\19878\Desktop\git-test\my-app>git status
On branch master
No commits yet
Untracked files:
(use "git add <file>..." to include in what will be committed)
.eslintrc.cjs
.gitignore
.prettierrc.json
.vscode/
README.md
env.d.ts
index.html
package.json
public/
src/
tsconfig.app.json
tsconfig.json
tsconfig.node.json
tsconfig.vitest.json
vite.config.ts
vitest.config.ts
nothing added to commit but untracked files present (use "git add" to track)
简单点讲, git status 如果提示了某个文件,说明文件有改动,如果 nothing to commit, working tree clean就表示没有修改。
状态简览
git status 命令的输出十分详细,但其用语有些繁琐。 Git 有一个选项可以帮你缩短状态命令的输出,这样可以以简洁的方式查看更改。 如果你使用 git status -s 命令或 git status --short 命令,你将得到一种格式更为紧凑的输出。
跟踪新文件
跟踪新文件或或者修改文件使用 git add <filename>
忽略文件
一般我们总会有些文件无需纳入 Git 的管理,也不希望它们总出现在未跟踪文件列表。 通常都是些自动生成的文件,比如日志文件,或者编译过程中创建的临时文件等。 在这种情况下,我们可以创建一个名为 .gitignore 的文件,列出要忽略的文件的模式。 来看一个实际的 .gitignore 例子:
$ cat .gitignore
*.[oa]
*~
第一行告诉 Git 忽略所有以 .o 或 .a 结尾的文件。一般这类对象文件和存档文件都是编译过程中出现的。 第二行告诉 Git 忽略所有名字以波浪符(~)结尾的文件,许多文本编辑软件(比如 Emacs)都用这样的文件名保存副本。 此外,你可能还需要忽略 log,tmp 或者 pid 目录,以及自动生成的文档等等。 要养成一开始就为你的新仓库设置好 .gitignore 文件的习惯,以免将来误提交这类无用的文件。
文件 .gitignore 的格式规范如下:
- 所有空行或者以 # 开头的行都会被 Git 忽略。
- 可以使用标准的 glob 模式匹配,它会递归地应用在整个工作区中。
- 匹配模式可以以(/)开头防止递归。
- 匹配模式可以以(/)结尾指定目录。
- 要忽略指定模式以外的文件或目录,可以在模式前加上叹号(!)取反。
所谓的 glob 模式是指 shell 所使用的简化了的正则表达式。 星号( *)匹配零个或多个任意字符;[abc] 匹配任何一个列在方括号中的字符 (这个例子要么匹配一个 a,要么匹配一个 b,要么匹配一个 c); 问号(?)只匹配一个任意字符;如果在方括号中使用短划线分隔两个字符, 表示所有在这两个字符范围内的都可以匹配(比如 [0-9] 表示匹配所有 0 到 9 的数字)。 使用两个星号()表示匹配任意中间目录,比如 a//z 可以匹配 a/z 、 a/b/z 或 a/b/c/z 等。
我们再看一个 .gitignore 文件的例子:
# 忽略所有的 .a 文件
*.a
# 但跟踪所有的 lib.a,即便你在前面忽略了 .a 文件
!lib.a
# 只忽略当前目录下的 TODO 文件,而不忽略 subdir/TODO
/TODO
# 忽略任何目录下名为 build 的文件夹
build/
# 忽略 doc/notes.txt,但不忽略 doc/server/arch.txt
doc/*.txt
# 忽略 doc/ 目录及其所有子目录下的 .pdf 文件
doc/**/*.pdf
查看已修改和未暂存的修改
使用 git diff ,但实际工作中,就直接利用编辑器插件的功能了,cli 命令适合学习,不适合实际生产,效率低。除非真没办法。
提交更新
提交更新,使用 git commit 命令
跳过使用暂存区
只要在提交的时候,给 git commit 加上 -a 选项,Git 就会自动把所有已经跟踪过的文件暂存起来一并提交,从而跳过 git add 步骤,举例:
git commit -a -m 'added new benchmarks'
移除文件
情况一:
手动删除工作目录下的文件,会在 git add时 提示 delete : xxx.md,这是使用 git rm <文件名>,就会添加到 未暂存清单,也就是初始状态。实际上我从来没注意这个,管他 是不是 delete 直接 commit
情况二:
我们想把文件从 Git 仓库中删除(亦即从暂存区域移除),但仍然希望保留在当前工作目录中。 换句话说,你想让文件保留在磁盘,但是并不想让 Git 继续跟踪。 当你忘记添加 .gitignore 文件,不小心把一个很大的日志文件或一堆 .a 这样的编译生成文件添加到暂存区时,这一做法尤其有用。 为达到这一目的,使用 --cached 选项:
实际上,很难出现这种情况,因为没写 .gitignore文件的情况很少,除非是删了,那再考虑这个吧。
git rm --cached README
git rm 命令后面可以列出文件或者目录的名字,也可以使用 glob 模式。比如:
git rm log/*.log
注意到星号 * 之前的反斜杠 \, 因为 Git 有它自己的文件模式扩展匹配方式,所以我们不用 shell 来帮忙展开。 此命令删除 log/ 目录下扩展名为 .log 的所有文件。 类似的比如:
git rm *~
移动文件
这个还真不知道。要在 Git 中对文件改名,可以这么做
git mv file_from file_to
运行 git mv 就相当于运行了下面三条命令:
mv README.md README
git rm README.md
git add README
查看提交历史
使用 git log命令
不传入任何参数的默认情况下,git log 会按时间先后顺序列出所有的提交,最近的更新排在最上面。
-p或 -patch
它会显示每次提交所引入的差异(按 补丁 的格式输出)。 你也可以限制显示的日志条目数量,例如使用 -2 选项来只显示最近的两次提交
git log -p -2
--stat
想看到每次提交的简略统计信息,可以使用选项,这个看上去还是很有用的,虽然现在有很多可视化工具。
git log --stat
--pretty
这个选项可以使用不同于默认格式的方式展示提交历史。
| -p | 按补丁格式显示每个提交引入的差异。 |
| \--stat | 显示每次提交的文件修改统计信息。 |
| \--shortstat | 只显示 --stat 中最后的行数修改添加移除统计。 |
| \--name-only | 仅在提交信息后显示已修改的文件清单。 |
| \--name-status | 显示新增、修改、删除的文件清单。 |
| \--abbrev-commit | 仅显示 SHA-1 校验和所有 40 个字符中的前几个字符。 |
| \--relative-date | 使用较短的相对时间而不是完整格式显示日期(比如“2 weeks ago”)。 |
| \--graph | 在日志旁以 ASCII 图形显示分支与合并历史。 |
| \--pretty | 使用其他格式显示历史提交信息。可用的选项包括 oneline、short、full、fuller 和 format(用来定义自己的格式)。 |
| \--oneline | \--pretty=oneline --abbrev-commit 合用的简写。 |
最有意思的是 format ,可以定制记录的显示格式。 这样的输出对后期提取分析格外有用——因为你知道输出的格式不会随着 Git 的更新而发生改变
$ git log --pretty=format:"%h - %an, %ar : %s"
ca82a6d - Scott Chacon, 6 years ago : changed the version number
085bb3b - Scott Chacon, 6 years ago : removed unnecessary test
a11bef0 - Scott Chacon, 6 years ago : first commit
限制输出长度
--since 和 --until 这种按照时间作限制的选项很有用
-<n>
仅显示最近的 n 条提交。
--since, --after
仅显示指定时间之后的提交。
--until, --before
仅显示指定时间之前的提交。
--author
仅显示作者匹配指定字符串的提交。
--committer
仅显示提交者匹配指定字符串的提交。
--grep
仅显示提交说明中包含指定字符串的提交。
-S
仅显示添加或删除内容匹配指定字符串的提交。
反正这个也不需要记,有需要用到看文档
撤销操作
覆盖上一个提交
git commit --amend
取消暂存的文件
git reset HEAD CONTRIBUTING.md
撤销修改
git checkout -- CONTRIBUTING.md
远程仓库的使用
查看远程仓库
指定选项 -v,会显示需要读写远程仓库使用的 Git 保存的简写与其对应的 URL
git remote -v
添加远程仓库
git remote add pb https://github.com/paulboone/ticgit
从远程仓库拉取
如果你的当前分支设置了跟踪远程分支(阅读下一节和 Git 分支 了解更多信息), 那么可以用 git pull 命令来自动抓取后合并该远程分支到当前分支。
这或许是个更加简单舒服的工作流程。默认情况下,git clone 命令会自动设置本地 master 分支跟踪克隆的远程仓库的 master 分支(或其它名字的默认分支)。
git fetch <remote>
推送到远程仓库
# git push <remote> <branch>
git push origin master
查看某个远程仓库
git remote show <remote>
git remote show origin
远程仓库的重命名与移除
你可以运行 git remote rename 来修改一个远程仓库的简写名。 例如,想要将 pb 重命名为 paul,可以用 git remote rename 这样做:
git remote rename pb paul
git remote rename
如果因为一些原因想要移除一个远程仓库——你已经从服务器上搬走了或不再想使用某一个特定的镜像了, 又或者某一个贡献者不再贡献了——可以使用 git remote remove 或 git remote rm :
git remote remove paul
一旦你使用这种方式删除了一个远程仓库,那么所有和这个远程仓库相关的远程跟踪分支以及配置信息也会一起被删除。
重新设置远程仓库的 地址
git remote set-url origin <新仓库的URL>
打标签
列出标签
只需要输入 git tag (可带上可选的 -l 选项 --list):
git tag
如果只对 1.8.5 系列感兴趣,可以运行:
git tag -l "v1.8.5*"
创建标签
Git 支持两种标签:轻量标签(lightweight)与附注标签(annotated)。
创建轻量标签
只需要提供标签名字
git tag v1.0
创建附注标签
运行 tag 命令时指定 -a 选项
-m 选项指定了一条将会存储在标签中的信息。 如果没有为附注标签指定一条信息,Git 会启动编辑器要求你输入信息。
git tag -a v1.0 -m "my version 1.0"
使用 git show 命令可以看到标签信息和与之对应的提交信息
给历史提交打标签
假设需要给 0e56fbe92712c324af913cedf01ba024627556e3该版本打 0.6版本标签
git tag -a v0.6 -m "v0.6" 0e56fbe92712c324af913cedf01ba024627556e3
共享标签
运行 git push origin <tagname>
git push origin v1.5
如果想要一次性推送很多标签,也可以使用带有 --tags 选项的 git push 命令。 这将会把所有不在远程仓库服务器上的标签全部传送到那里。
git push origin --tags
删除标签
删除掉你本地仓库上的标签
git tag -d <tagname>
git tag -d v1.4
删除远程仓库标签
第一种是 git push <remote> :refs/tags/<tagname> :
git push origin :refs/tags/v1.4-lw
第二种是 git push origin --delete <tagname>
git push origin --delete v1.4
标签输出
如果你想查看某个标签所指向的文件版本,可以使用 git checkout 命令, 虽然这会使你的仓库处于“分离头指针(detached HEAD)”的状态——这个状态有些不好的副作用:
在“分离头指针”状态下,如果你做了某些更改然后提交它们,标签不会发生变化, 但你的新提交将不属于任何分支,并且将无法访问,除非通过确切的提交哈希才能访问。 因此,如果你需要进行更改,比如你要修复旧版本中的错误,那么通常需要创建一个新分支:
git checkout -b version2 v2.0.0
如果在这之后又进行了一次提交,version2 分支就会因为这个改动向前移动, 此时它就会和 v2.0.0 标签稍微有些不同,这时就要当心了。
标签输出这段没理解,如果实际用到了,再看,知道有这个东西
git别名
创建别名这个东西看起来还是很有用的
git config 文件来轻松地为每一个命令设置一个别名
$ git config --global alias.co checkout
$ git config --global alias.br branch
$ git config --global alias.ci commit
$ git config --global alias.st status
在创建你认为应该存在的命令时这个技术会很有用。 例如,为了解决取消暂存文件的易用性问题,可以向 Git 中添加你自己的 取消暂存别名
git config --global alias.unstage 'reset HEAD --'
这会使下面的两个命令等价
$ git unstage fileA
$ git reset HEAD -- fileA
或者添加 last命令,实现查看最后一次提交信息
git config --global alias.last 'log -1 HEAD'
可以看出,Git 只是简单地将别名替换为对应的命令。 然而,你可能想要执行外部命令,而不是一个 Git 子命令。 如果是那样的话,可以在命令前面加入 ! 符号。 如果你自己要写一些与 Git 仓库协作的工具的话,那会很有用。 我们现在演示将 git visual 定义为 gitk 的别名:
git config --global alias.visual '!gitk'
基础篇总结
- 学习了如何创建一个
git仓库,或者从远程fetch/clone一个仓库。 - 学习了如何查看文件状态,未跟踪 和 已跟踪 状态
- 学习了提交到暂存区,
git add命令 - 学习了提交更新,
git commit命令 - 学习了如何撤销提交,
git reset HEAD - 学习了查看提交历史,简单查看、详细查看、指定条件查看
- 学习了远程仓库相关的操作,比如
remove、push - 学习了如何创建标签(附注标签和轻量标签),给历史版本打标签,查看标签,删除标签(本地和远程删除)
- 学习了 git 别名,简化命令操作
东西还是很多的,常用命令要熟练掌握,比如 add``commit``push,其他命令以及知识点要有印象,至少得能看得懂。反正遇到不会的就查,然后补充文档。
git 分支
分支应该是一个重点了,如果一个人做项目倒也无所谓,但是多人协作开发,就显得尤为重要了。
参考:Git - 分支简介
分支的新建与合并
分支创建
使用 git branch 命令:
git branch dev
使用 git log 命令查看各个分支当前所指的对象。 提供这一功能的参数是 --decorate。
git log --oneline --decorate
切换分支
使用 git checkout 命令。比如切换到 dev分支
git checkout dev
创建新分支并切换到那个分支
git checkout -b <newbranchname>
项目分叉历史
你可以简单地使用 git log 命令查看分叉历史。 运行 git log --oneline --decorate --graph --all ,它会输出你的提交历史、各个分支的指向以及项目的分支分叉情况。
git log --oneline --decorate --graph --all
合并分支
git merge hotfix
删除分支
git branch -d hotfix
分支的合并
合并到 master分支
git checkout master
git merge iss53
遇到冲突时的分支合并
涉及到同一个文件的同一处,在合并它们的时候就会产生合并冲突:
说白话就是,把有冲突的地方保留一个,或者修改为想要的。手动修改
如果你想使用图形化工具来解决冲突,你可以运行 git mergetool,
分支管理
查看每一个分支的最后一次提交,可以运行 git branch -v 命令
--merged 与 --no-merged 这两个有用的选项可以过滤这个列表中已经合并或尚未合并到当前分支的分支。 如果要查看哪些分支已经合并到当前分支,可以运行 git branch --merged:
分支开发工作流
长期分支
远程分支
远程引用是对远程仓库的引用(指针),包括分支、标签等等。 你可以通过 git ls-remote <remote> 来显式地获得远程引用的完整列表, 或者通过 git remote show <remote> 获得远程分支的更多信息。 然而,一个更常见的做法是利用远程跟踪分支。
推送
跟踪
拉取
删除远程分支
变基
在 Git 中整合来自不同分支的修改主要有两种方法:merge 以及 rebase。 在本节中我们将学习什么是“变基”,怎样使用“变基”,并将展示该操作的惊艳之处,以及指出在何种情况下你应避免使用它。