Git教程
前言
此文章内容较复杂,合并了进阶贡献的 Git 教程部分。此文章主要由 Suikalley 等 NCEPUwiki-Group 成员编写、整合。
此文章对于Git的说明并不全面,更深层次的内容请自行学习。
Git是什么
Git是一个强大的分布式版本控制系统,核心目标是高效地管理项目文件的变更历史。它允许你记录代码的每一次改动,并可以轻松回溯到任何历史版本。
可以通过B站视频学习
我们极其推荐先观看这个视频学习一次
安装
在使用 Git 前需要先安装 Git(Git下载链接)
Linux:发行版官方仓库下载
Windows:官网下载安装即可/使用winget install git
Git 设置
在第一次使用Git需要进行一些配置,
git config --global user.name "your_user_name"
git config --global user.email "Your_Email_Address"
# --local(可省略) 本地配置,只对本地仓库有效
# --global 全局配置,所有仓库生效
# --system 系统配置,对所有用户生效
git config --global --list
# 查看git的配置信息这些配置的作用是:在修改之后,可以显示修改人信息
基本概念
区域概述 / Synopsis of Area
- 工作区 / Working Directory
当前文件夹(除.git/的部分),也就是你正在查看和编辑的项目文件副本
- 暂存区 / Staging Area/Index
位于 .git/index/ 临时存储区域,用于准备下一次提交的中间区域。它记录了工作区中哪些文件的哪些变更将被纳入下一次提交的版本快照中。
- 本地仓库 / Local Repository
有本地仓库和远程仓库。
一个由 Git 管理的项目目录(文件夹)。仓库内包含你的项目文件和一个名为 .git 的隐藏子目录,该目录存储了所有的版本历史数据。
文件状态 / Status of file
git status #查看仓库的状态- Untrack files
新创建还未被Git追踪的文件
- Unmodified files
已经被Git管理起来但是文件内容没有变化
- Modified files
已经修改但是未放入暂存区中
- Staged files
已经添加到暂存区中文件
分支(Branch)
一个指向某个提交的可变指针。默认的主分支通常名为 main 或 master。创建新分支意味着从某个点开始创建一条独立的开发线,分支之间的工作可以互不干扰。
两种开始方式
先通过下面两张流程图了解 Git 最常用的两种开始方式,后面的章节会对每一步做详细说明。
路线一:从 0 开始(自己的新项目)
先创建本地仓库,再在代码托管平台创建远程仓库,最后把两者连接起来。对应下文「初始化」和「连接一个远程仓库」。
路线二:克隆已有仓库
参与别人的项目,或取回自己的代码用此方法,参与NCEPUwiki亦是如此。
只需新建一个文件夹,再用 git clone 把远程仓库完整下载到本地。对应下文「克隆一个远程仓库」。
初始化
如果是修改别人的项目,请跳过这一步
- 创建文件夹,又称为Working Directory
创建一个项目所在的文件夹,所有工作文件都在里面。
比如在桌面创建一个VscodeGitTest的文件夹,内部放入一个Test.md文件。
mkdir ~/Code/Repo
# Windows可手动创建,不必输命令- 初始化,在该文件夹下创建.git文件夹
Windows请打开 cmd 或者 powershell。
包含暂存区stage/index,创建的第一个分支master(main),以及指向master(main)的一个指针,叫HEAD。
Git 3.0 版本后主分支默认名称为 main (先前为master)。
cd ~/Code/Repo
# 进入文件夹初始化仓库
git init
# 在文件夹下创建.git文件夹可以看到文件夹中多出一个隐藏文件夹 .git , 说明该目录已经被git管理了,也就是说现在它是一个仓库了。
连接一个远程仓库
创建一个远程仓库
常见的代码仓库托管平台:
- GitHub: github.com
- Gitee : gitee.com
- GitLab : gitlab.com
将本地的代码上传到云端,这样可以多人协作、异地办公
链接本地与远程仓库
- 在本地添加一个远程仓库。git clone 时自动设置
git remote add <自定义短名> <仓库URL>
# 例子
git remote add origin [email protected]
# 查看当前本地仓库对应远程仓库的别名和地址
git remote -v
# 展示远程仓库分支
git remote show <branch_name>
# 指定本地分支为main
git branch -M main- 把本地main分支和远程origin仓库main分支关联起来
git push -u origin main:main
# -u, --upstream
# main:main (可简写为main)之后运行 git push 或 git pull,Git自动知道操作哪个远程分支和本地分支
克隆一个远程仓库
将别人的仓库克隆到本地,以Github上的仓库 NCEPUwiki 为例。
- 建立一个新文件夹,用来存放仓库
- 使用命令行工具进入此文件夹
- 复制仓库链接
- 执行git clone URL
git clone https://github.com/NCEPUwiki/NCEPUwiki.git完成后NCEPUwiki仓库就被克隆在了本地
常见命令
此流程图展示了对repo进行修改的大致流程及命令,已经可以应对包括NCEPUwiki贡献的绝大部分场景。后文提到的更多的命令可以不了解。
git pull
把远程Repo某branch的修改拉取合并到本地Repo的某个branch。
<远程仓库名><远程分支名>可以省略,默认拉取仓库别名origin的main分支。
git pull <远程仓库名><远程分支名>:<本地分支名>git fetch
只获取远程仓库修改,并不自动合并到本地仓库
# 获取所有远程分支信息
git fetch
# 列出所有远程分支(例如 origin/main, origin/develop)
git branch -r
# 查看本地和所有远程分支的完整列表
git branch -a
# 只从 origin 获取 main 分支的更新
git fetch origin maingit push
把本地Repo的某个branch修改推送到远程Repo的对应branch
- 远程仓库名:默认是 origin(clone 时自动设置)。
- 本地分支名:要推送的本地分支。
- 远程分支名:目标远程分支(通常与本地分支同名,可省略)。
git push <远程仓库名> <本地分支名>:<远程分支名>git status 查看仓库的状态
当前仓库处于哪一个分支
有哪些文件以及这些文件处在怎样状态
git status -s 简略模式
git add 添加到暂存区
git add filename
git add directory
git add . #当前文件夹全部文件将上面提到的Test.md添加到缓存区(初始化后的仓库中原来的文件也可以看成一种修改) 
可以使用 git status 来查看当前工作区和暂存区的状态
可以看到目前工作区是默认主分支master,没有提交记录,有一个文件Test.md处于暂存区。
git commit 提交
每次提交会将被暂存的更改永久记录到本地仓库中,并生成一个唯一的哈希值(如 fd6a3a0...)作为标识。
只会提交暂存区中文件,不提交工作区中其他文件。
git commit -m '提交信息'
git commit -a -m '提交信息'
git commit -am '提交信息'
# 两者等同,对已经被追踪的所有文件添加暂存并提交提交处于暂存区的Test.md, -m后面写这一次提交的备注,如果不加 -m git会为我们打开编辑器让我们写备注
使用 git log 查看提交记录
可以看到现在有一条提交记录,备注就是我们写的commitNote
git log 查看提交记录
- commit 每次提交都有唯一ID
- Author 提交者 Email邮箱
- Date 提交日期
- annotation 注释信息
git log
commit 475c14ea046dd20d7e2201a1b300369f3f291dc5
Author: JavidPack <[email protected]m>
Date: Mon May 19 13:49:25 2025 -0600
Updated Basic Netcode (markdown)查看简洁的提交记录
git log --oneline
529680a Updated Basic Tile Entity (markdown)查看分支图
git log --graph --oneline --decorate --allgit reflog 查看操作的历史记录
git中所有操作都可以回溯,可以找到版本号回退
git diff 查看差异
查看文件在工作区,暂存区,版本库之间差异
还可以查看文件在两个特定版本之间的差异,或者文件在两个分支之间的差异
可在命令最后加上文件名,只查看该文件的差异内容
git diff HEAD^ HEAD~3 test1显示发生更改的文件和更改的详细信息
- 提示发生变更的文件
- git会将文件的内容使用hash算法生成40位hash值,只显示hash值前7位,最后是文件权限
- 绿色文字是新添加内容,红色文字表示删除的内容
git diff
diff --git a/test2 b/test2
index be10852..ba76164 100644
--- a/test2
+++ b/test2
@@ -1 +1,3 @@
+
+ss
???git diff 比较工作区和暂存区之间差异
git diff HEAD 比较工作区和版本库之间差异
git diff --cached 比较暂存区和版本库之间差异
git diff ID1/HEAD ID2/HEAD 比较两个特定版本之间的差异
git diff 分支名1 分支名2 比较两个分支之间差异
git rm 删除文件
git rm 同时删除工作区和暂存区文件
git rm test2
# 被删除的文件仍然存在于版本库git rm --cached 只删除暂存区文件
git rm --cached other.log
# 被删除的文件仍然存在于版本库和工作区git ls-files 按文件状态列出文件
-c,--cached (无参数默认选项) 列出暂存区(staged)中所有文件
-d,--deleted 列出暂存区(staged)中存在而中已删除的文件
-m,--modified 列出工作区中修改但未暂存的文件
-o,--others 显示未跟踪的文件
--unmerged 显示存在合并冲突且未合并的文件
撤销
git撤销操作:https://www.bilibili.com/video/BV1ne4y1S7S9/
- 撤销工作区(working area)文件修改
git checkout <change_file>
git restore <change_file>- 撤销暂存区(staging)文件修改,但保留工作区(working area)的修改 (即撤销git add操作)
git reset <change_file>
git restore --staged <change_file>- 撤销暂存区(staging)文件修改,也撤销工作区(working area)的修改 (三个区域同步回到本次commit的状态)
git checkout HEAD <change_file>- 仅撤销本次commit,保留暂存区和工作区修改
git reset --soft HEAD~1
# 回到上次commit(HEAD~1),--soft保留暂存区和工作区- 撤销本次commit和暂存区修改,保留工作区
git reset HEAD~1
git reset --mixed HEAD\~1- 撤销本次commit、暂存区和工作区修改(三个区域同步回到上次commit的状态)
git reset --hard HEAD~1回退版本
git reset
HEAD指向分支的最新提交节点
HEAD\^ HEAD1 指向当前版本的上一个版本
HEAD\^\^ HEAD2 指向当前版本的上两个版本
HEAD\~8 指向当前版本的前8个版本
git reset --soft
回退到某个版本,并保留暂存区和工作区的内容
git reset --soft 版本ID前7位
git reset HEAD^ # HEAD指针
# 例
git reset --soft 529680agit reset --hard
回退到某个版本,并清空暂存区和工作区的内容
git reset --mixed
回退到某个版本,清空暂存区,保留工作区的内容
--mixed 是留空默认参数
git revert添加负向提交抵消先前修改
本质是添加一个commit,而这个commit刚好是先前的commit反过来
git revert的好处是能够撤销中间任意一个 commit
对于远程仓库的公有分支,只应前进不应后退,只能使用git revert不能使用git reset
分支命令
分支的使用场景
多个开发人员在自己的分支上进行开发,最后再合并到主线代码库
在一个分支上进行新功能的开发,或者建立问题修复分支来处理bug
让主线代码仓库处于一个随时可用的稳定状态
分支类别
- 主分支 main/master
Linus Torwards开发git时使用master作为仓库的主分支,但由于政治文化因素,master有主人掌控的歧视意味,现在推荐使用main作为主分支名称
原则:应当始终保持main分支处于随时可以发布的状态
- 开发分支
推荐名称:dev(development)
所有新的开发都应当提交到该分支中进行CI测试,集中许多提交后将dev分支一次性合并git merge回main分支,保证main分支提交记录整洁
- 稳定分支
推荐名称:stable
定期从main分叉出stable分支,每隔一段时间将bug fix向后移植得到稳定版本,维护较长一段时间丢弃
可以有多个stable分支,长期维护多年
git branch
git branch 查看分支,以及当前处于哪个分支
git branch branch-name 创建名为branch-name的新分支(但并未切换到新分支)
创建新分支之后可以发现我们仍然在主分支master上
git branch -d name 删除名为branch-name且已经被合并的分支(不能删除未被合并的分支)
git branch -D name 强制删除名为branch-name分支
git switch
git switch name切换到name分支
git checkout
git checkout既可用于切换分支,又可用于恢复文件,如果分支名和文件名相同,优先切换分支。容易引起歧义
不同分支的文件在同一个目录下, 切换时会出现文件的变化
可以看到现在已经在我们创建的newBranch上了。
git merge
将不同分支合并到主线分支中,并在主线中增加一次提交记录
优点:不破坏原分支的提交历史,方便回溯和查看
缺点:会产生额外的提交节点,分支图复杂
git merge <将被合并的分支名>
# 当前分支为合并的主分支,合并默认要提交信息
# 合并分支并不会删除分支
git merge --abort
# 终止合并git rebase
将不同分支合并到主线分支,并将分支的所有修改记录添加到主线。
可以在将主线合并到其他分支。
优点:不会新增额外的提交记录,形成线性历史,直观干净
缺点:会改变提交历史,避免在共享分支使用。多用于单人开发
git rebase main
# 将当前所在分支变基到main分支上- Resolve merge confilcts
如果两个分支修改内容没有重合部分,则没有冲突,git会自动合并
如果两个分支修改了同一文件同一行代码,需要手工修改冲突文件,再提交
Git仓库内配置文件
.gitignore
参考文档:https://github.com/github/gitignore.git
.gitignore文件应当被git追踪
仓库中不应被git追踪的文件:能够自动生成的文件,不希望别人知道的文件
- 系统,软件自动生成的文件
- 编译构建文件
- 程序运行生成的日志,缓存等临时文件
- 涉及身份,密码,口令,密钥等敏感文件
语法规则
- ## 开头的行是 注释
- 空行会被忽略
.gitignore中记录的文件名会被git忽略(前提是不能是已经被添加到版本库中的文件)
.gitignore中可记录文件夹,文件夹名以/结尾(注意:git默认不将空文件夹添加到仓库中)
# 忽略所有 .o 和 .exe 文件
*.o
*.exe
# 但跟踪 lib.o(否定示例)
!lib.o
# 忽略根目录下的 /debug 目录(整个目录)
/debug/
# 忽略任意目录下的 /temp 目录(注意:没有前导斜杠,会递归匹配)
temp/
# 忽略 docs/ 目录下所有 .bak 文件,但不忽略 docs/ 子目录中的 .bak
docs/*.bak
# 忽略 docs/ 目录下的所有子目录中的 .bak 文件
docs/**/*.bak
# 忽略所有 .log 文件,但 important.log 除外
*.log
!important.log
# 忽略 build/ 目录下所有内容,但保留 build/README.md
build/*
!build/README.md
# 忽略 .config 目录下所有内容,同时忽略 .config/ 目录本身
.config/补充说明
- .gitignore以放在仓库的任意目录中,其作用域为当前目录及所有子目录。
- 子目录中的.gitignore 会覆盖父目录的规则(更具体优先)。
- 已经被Git跟踪的文件不受.gitignore 影响
- 要停止跟踪,需要使用 git rm --cached <file>。
.gitmodules
参考文章: https://zhuanlan.zhihu.com/p/87053283
简介: .gitmodules 是 Git 项目中用来管理子模块(submodule)的配置文件。当你的仓库需要引用另一个外部 Git 仓库,且希望保持两个仓库相对独立时,子模块功能会派上用场,而 .gitmodules 文件则记录了这些子模块的元信息。
面对比较复杂的项目,我们有可能会将代码根据功能拆解成不同的子模块。主项目对子模块有依赖关系,却又并不关心子模块的内部开发流程细节。这种情况下,通常不会把所有源码都放在同一个Git仓库中。
.gitmodules典型使用场景
- 依赖外部库:希望将第三方库固定在某一个提交,随主项目一起构建。
- 大型项目拆分:将不同模块独立成仓库,但需要统一管理。
- 共享通用组件:多个项目复用同一份子模块代码。
.gitattributes
参考文章:https://zhuanlan.zhihu.com/p/108266134
简介:.gitattributes 是一个让 Git 的工作方式变得“听话”的配置文件,可以从根源上解决跨平台协作时最令人头疼的换行符混乱、文件损坏等问题。通过它,可以为不同的文件精准定义 Git 的处理方式。
当执行 git 动作时,.gitattributes 文件允许你指定由 git 使用的文件和路径的属性,例如:git commit 等。换句话说,每当有文件保存或者创建时,git 会根据指定的属性来自动地保存。
Git 搭配 Vscode
Vscode(全称 Visual Studio Code)是一款由微软推出的免费、开源、跨平台的代码编辑器。
Vscode 提供了操作git的图形化工具,可以简单直观地使用git。
初始化仓库
准备一个文件夹(项目文件夹) 用Vscode打开这个文件夹,演示中在文件夹中放了一个空md文件Test.md。
在 VSCode 左边的活动栏中找到源代码管理选项。 点击初始化仓库来将当前目录纳入到git版本管理。
点击初始化仓库后
此时我们可以看到新建的文件为绿色,且后面有 U 字提示;U 意为 Untracked 未追踪,也就是说此文件目前仅在我们本地,未被 git 进行跟踪。
添加文件至暂存区
点击所要操作文件后面的 “+”,即可将文件添加至暂存区,相当于执行命令 git add
此时文件名仍然为绿色,但是后面的 U 变成了 A,A 则意为此文件已在暂存区。
在消息框中输入相关备注,然后点击 √提交 即可进行一次提交,也可使用 Ctrl+Enter 快捷键直接提交,这会将暂存区的文件提交至 git, 相当于执行命令 git commit
修改提交后的文件
提交后,点回到资源管理器,对文件进行修改
此时文件名变为黄色,且有提示字母 M;M 意为 modify,即已修改, 想要撤销修改,进入源代码管理,点击返回箭头放弃更改即可。
查看/新建/切换分支
点击 vs code 底部状态栏的分支选项即可显示项目中的分支,此处的 main 意为当前所在分支为 main;如下图所示,项目中只有一个main分支
点击 +创建新分支...,并输入新分支的名字可以创建一个新分支。
此时可以看到已经有两个分支了,切换分支只需点击对应分支名称即可
推送和拉取
如遇推送或拉取操作失败,可能是由于网络连接问题所致,建议尝试使用网络代理工具。
第一次需要配置远程仓库
点击 添加远程存储库... 来添加一个远程仓库,仓库Url可以在仓库的Github中找到
图示为NCEPUwiki Github仓库的Url
配置好后就可以进行拉取推送操作了
若要向默认远程仓库推送或拉取,直接推送和拉取按钮。若要自行选择远程仓库,请使用下方“推送”或“拉取”菜单中的“推送到”与“拉取自”选项。
相当于执行命令 git push 和 git pull
克隆
在Vscode左上角文件栏下选择新建窗口,并在欢迎中的启动选择克隆Git仓库...,输入远程仓库的URL地址以克隆Github中的项目。
相当于执行命令 git clone
Github
这是什么
GitHub 是一个基于 Git 的代码托管和协作平台,它让个人开发者和团队能够更轻松地管理代码版本、协同工作以及分享项目。关于Github全面的快速入门请移步GitHub 入门文档
与Git的关系
Github不等于Git,Git 是在本地计算机上运行的工具,负责版本控制的所有基础操作。而 GitHub 则提供了一个中心化的服务器来托管本地 Git 仓库,并在此基础上增加了图形化界面、协作工具(如 Pull Requests、Issues)和社交功能。
仓库(repositories)
和git的仓库相似,只不过代码文件是在服务器而非用户本机,因此Github仓库也被称为远程仓库(Remote Repository)。
你可以使用 git remote add [为远程仓库指定的名称] [远程仓库的Url地址] 来添加一个远程仓库。进入一个项目的Code首页(即一点击默认进入的页面),点击绿色的Code按钮,就可以看到一个项目的HTTP Url地址。
使用 git remote -v 可以查看已添加的远程仓库。
分支(branches)
同git的分支,唯一区别在于代码是否在本地。
提交(commits)
同git的提交,只是由远程仓库管理。
结合Github、Vscode和git进行项目开发
个人项目
GitHub 个人项目 就是你存放在 GitHub 平台上的、由你自己独立或主导完成的代码仓库的集合。
Fork
Fork 是对一个仓库的克隆。 forks 常被用于去更改别人的项目(贡献代码给已经开源的项目)或者使用别人的项目作为你自己想法的初始开发点。 比如你想要为NCEPUwiki项目做出贡献,你可以:
- Fork 这个仓库(你可以直接在NCEPUwiki的页面上点击fork按钮以完成fork),将别人的仓库复制一份到你自己的 GitHub 账户下
然后在新的界面点击Create fork,这样就获得了一个克隆仓库
从Vscode拉取/拉取仓库的代码
使用Vscode进行代码修改(最好建立一个新的分支以保持主分支的整洁)
将你本地仓库的修改推送到你的 GitHub 远程仓库(即你 Fork 的那个)。
在你克隆的项目点击Compare & pull request向NCEPUwiki提交一个pull requset或者在原项目中点击 Pull requests中的New pull request以创建一个pull request
之后等待项目作者合并分支即可。
Pull Request
Pull Request 简称PR。
在仓库页面上,你会看到一个pull request按钮。点击它,选择你的新分支和原始仓库的目标分支(通常是 main 或 master),填写 PR 的标题和描述,解释你的更改和为什么应该接受这些更改。 然后等待项目的管理员同意(或者拒绝)这个合并请求。
Reference
官网(英):https://git-scm.com
官网(中):https://git-scm.cn/
Git logo:https://git-scm.com/downloads/logos
用户参考手册:https://git-scm.com/docs/user-manual
命令参考手册:https://git-scm.com/docs
Pro Git 电子书(中):https://git-scm.com/book/zh/v2
Pro Git 电子书(英):https://git-scm.com/book/en/v2



































