Git新手实用指南
Git简介
Git是一种分布式版本控制系统,主要用于跟踪代码的变更和管理项目的版本。它允许开发者在本地仓库进行操作,并通过远程仓库协作。Git的分支管理功能强大,支持多人并行开发和高效的合并。它通过SHA-1哈希确保数据的完整性,能够灵活处理各种代码版本和历史,使得协作和代码管理更加便捷。
当前Git可视化工具非常多,在代码协作的过程中,还是比较推荐使用Git可视化系统进行代码管理,这样大大提高了工作效率。
安装与配置
Git的安装与配置
Git的安装非常简单,只需要到官网下载git客户端,然后按默认配置进行安装。
在使用 Git 时,为了标识提交记录的所有者,需要配置用户名和邮箱。你可以通过以下命令来设置:
- 设置全局用户名和邮箱
git config --global user.name "你的用户名"
git config --global user.email "你的邮箱地址"
- 设置仓库级别的用户名和邮箱
如果你希望只针对某个特定仓库设置用户名和邮箱,可以进入该仓库的目录,然后执行以下命令:
git config user.name "你的用户名"
git config user.email "你的邮箱地址"
- 验证配置
你可以通过以下命令查看当前的用户名和邮箱配置:
git config --global --list
或者查看某个仓库的配置:
git config --list
Git 使用 SSH 密钥来进行身份验证,确保安全连接到远程仓库。生成 SSH 密钥的步骤如下:
1.生成 SSH 密钥
在你的终端或命令行中,输入以下命令:
ssh-keygen -t rsa -b 4096 -C "你的邮箱地址"
-t rsa
表示生成 RSA 类型的密钥。-b 4096
指定密钥的长度为 4096 位(可以选择其他长度)。-C
用来添加注释,这里通常使用邮箱地址。
这样就生成了ssh密钥,它通常会在**c盘当前用户主目录/.ssh/**文件夹下
2.添加公钥到远程 Git 平台
GitHub:前往 GitHub,点击头像,选择 Settings -> SSH and GPG keys -> New SSH Key,然后将生成的公钥粘贴到文本框中。
Git相关基本概念
仓库(Repository)
仓库是 Git 存储和管理项目的核心概念,它包含了所有文件的历史记录。仓库可以分为两种:本地仓库:指你在本地计算机上创建和管理的仓库。通过命令 git init 可以创建一个本地仓库。所有的提交和分支都可以在本地操作。
远程仓库:指托管在远程服务器上的仓库,例如 GitHub、GitLab、Gitee 等。远程仓库便于团队协作,开发者可以通过 git clone 下载远程仓库,也可以通过 git push 上传本地更改。工作区(Working Directory)
工作区就是你当前项目的文件目录,包含你正在编辑的所有文件。当你修改一个文件并保存时,这些变更发生在工作区。工作区是你操作的主要场所,在这里你可以对文件进行增删改等操作。暂存区(Staging Area)
暂存区(也称为索引 Index)是 Git 中一个临时区域,用于保存你即将提交的更改。每次使用 git add 命令时,文件的变更就会被添加到暂存区。暂存区的存在使得你可以选择性地提交某些修改,而不是将工作区中的所有修改一并提交。本地仓库(Local Repository)
本地仓库是 Git 中存储所有历史版本和元数据的地方。通过 git commit 命令,将暂存区的更改提交到本地仓库。每次提交会生成一个唯一的 SHA-1 哈希值,用于标识该次提交。远程仓库(Remote Repository)
远程仓库是 Git 用来存储项目的远程副本,通常托管在服务器上。你可以通过命令git remote add 添加远程仓库的 URL 地址
,以便进行推送或拉取操作。远程仓库是团队协作开发的基础,允许多名开发者共享项目代码。提交(Commit)
提交是 Git 中记录更改的基本单元。每次执行 git commit,都会在本地仓库中创建一个新的快照,并保存此次提交的详细信息(包括作者、时间和更改的内容)。提交记录会生成一个唯一的 SHA-1 哈希值,标识每次提交。提交可以视为对代码历史的一个“快照”。分支(Branch)
分支是 Git 中的一个核心概念,用于隔离不同的开发线。每个分支都是从主线中独立出来的开发轨迹。Git 默认会创建一个 main 或 master 分支,用户可以通过命令 git branch创建新分支,然后通过 git checkout 切换到该分支。分支的存在使得并行开发、修复 Bug 和特性开发变得简单。 标签(Tag)
标签用于给某个特定的提交创建一个固定的标记,通常用于版本发布。HEAD
HEAD 是 Git 中的一个特殊指针,它指向你当前所在的分支的最新提交。它是 Git 跟踪当前操作位置的方式。当你切换分支时,HEAD 也会指向新分支的最新提交。合并(Merge)
合并是将不同分支上的修改合并到一个分支中的操作。通过 git merge命令,你可以将 分支的修改合并到当前分支。 冲突(Conflict)
当两个分支对同一文件的同一部分做出不同的修改时,Git 会产生冲突。冲突会阻止合并操作完成,开发者需要手动解决冲突,然后再提交。Git 会标记冲突部分,帮助你进行手动合并。Rebase
Rebase 是 Git 中的一种分支整合方法,它的作用是将一个分支的提交记录重新应用到另一条分支的顶部。与 merge 不同,rebase 会重写提交历史,将目标分支的提交线性化。通过 git rebase命令,你可以将当前分支的提交应用到 分支的顶部。rebase 主要用于保持提交历史的整洁。 远程追踪分支(Remote Tracking Branch)
远程追踪分支是指向远程仓库中对应分支的本地引用,它们的名字通常以 origin/branch-name 形式存在。例如,origin/main 表示远程仓库 origin 中的 main 分支。远程追踪分支使得你可以同步和追踪远程仓库的变更。Fork
Fork 是托管平台(如 GitHub 和 GitLab)提供的功能,它允许你从一个公开的项目创建一个副本到你自己的账户中。Fork 的主要作用是方便在不影响原始项目的情况下进行独立开发和改动。Fork 项目之后,你可以修改它、提交更改,并通过创建 Pull Request 将改动提交回原始项目。Pull Request(PR)
Pull Request 是托管平台中一种用于代码协作的机制。开发者可以在自己的分支或 Fork 中做出修改,然后创建一个 Pull Request,通知仓库的管理员他们希望将这些修改合并到主分支中。Pull Request 通常伴随代码审查和讨论,用于确保代码质量。
常用命令
git init
初始化一个新的 Git 仓库。通常在你从零开始创建项目时使用:git init
git remote
管理远程仓库。可以查看当前仓库的所有远程连接、添加远程仓库、删除远程仓库等:git remote -v # 查看当前所有的远程仓库 git remote add origin <url> # 添加一个名为 origin 的远程仓库 git remote remove origin # 删除远程仓库
git status
查看当前仓库的状态,包括哪些文件被修改、哪些文件处于暂存区,以及未被跟踪的文件等:git status
git log
查看仓库的提交历史。你可以使用不同的参数来获取更详细或简洁的日志:git log # 查看提交历史 git log --oneline # 简洁的单行提交历史
git diff
查看工作区中哪些文件或内容被修改。可以用来对比不同提交或分支之间的差异:git diff # 查看当前工作区的更改 git diff <commit1> <commit2> # 对比两个提交之间的差异
git add
将文件的更改添加到暂存区,以便进行下一步的提交。可以添加单个文件,也可以一次性添加所有更改的文件:git add <file> # 添加单个文件 git add . # 添加所有修改过的文件
git commit
将暂存区的更改提交到本地仓库,并且需要附带提交消息来描述这次提交的内容:git commit -m "Add new feature"
git stash
暂存当前的未提交更改,并在以后取出。适合在你正在开发时突然需要切换分支但不想提交当前工作时使用:git stash # 暂存当前更改 git stash apply # 恢复暂存的更改
git branch
列出所有分支,创建新分支,或者删除分支:git branch # 列出所有分支 git branch <branch> # 创建新分支 git branch -d <branch> # 删除分支
git checkout
切换到其他分支,或检出某个提交。也可以用来创建和切换新分支:git checkout <branch> # 切换到已有的分支 git checkout -b <new-branch> # 创建并切换到新分支
git merge
合并两个分支的更改。通常用于将其他分支的更改合并到当前分支:git merge <branch>
git rebase
将一个分支的提交“重新基准化”到另一个分支的顶部。可以用来整理提交历史:git rebase <branch>
git fetch
从远程仓库中获取更新,但不自动合并。git fetch
只会下载远程分支的更新到本地,而不会直接影响当前工作区的文件:git fetch origin
git reset
回退到某个特定的提交。你可以使用不同的参数来控制回退的程度:git reset --hard <commit> # 将工作区、暂存区和提交记录全部回退到某个提交 git reset --soft <commit> # 只回退提交记录,保留暂存区的内容
git tag
给特定的提交打标签,通常用于标记发布版本:git tag <tagname> # 创建一个新的标签 git tag -a <tagname> -m "message" # 创建带注释的标签 git push origin <tagname> # 推送标签到远程仓库
Git提交规范
目前流传比较广泛的就是Git提交规范
提交信息结构
Git提交消息的基本结构如下
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
<type>
: 提交的类型。一般为fix
、feat
、build
、chore
、ci
、docs
、style
、refactor
、perf
、test
[optional scope]
: 可选的范围,用于描述该提交影响的代码区域或模块。<description>
: 提交的简短描述,概述了更改的内容。[optional body]
: 可选的详细信息,描述更改的原因或背景。[optional footer(s)]
: 可选的页脚,通常用于提供额外信息,如BREAKING CHANGE
。
提交类型
fix
: 修复代码中的错误。feat
: 引入新功能。build
: 更改构建系统或外部依赖项的提交。chore
: 维护性提交,通常不影响源代码或测试。ci
: 与持续集成相关的更改。docs
: 文档相关的更改。style
: 代码格式方面的更改(不影响功能)。refactor
: 代码重构的提交,不会修复错误或添加功能。perf
: 性能优化的提交。test
: 测试相关的更改。
注:BREAKING CHANGE
:表示提交中包含该标识的内容表示此次更改会影响 API 的向后兼容性,通常会引发使用者的代码中断。例如:
- 在页脚中声明: 通过
BREAKING CHANGE: <description>
的方式描述具体的破坏性更改。 - 在类型后附加
!
: 例如,feat!
或fix!
代表这个提交引入了破坏性更改。
相关工具
Jetbrains全家桶系列中的插件Git Commit Message Helper
git merge 和 git rebase
git merge
和 git rebase
是版本控制中非常重要的操作,而它们在处理冲突时也发挥着关键作用。
注:git pull
= git fetch
+git merge
1. git merge
定义:
git merge
是将一个分支的更改合并到当前分支中。这通常用于将特性分支合并回主分支(如main
或develop
),以整合多个开发者的工作。工作原理:
- Git 会自动尝试合并两个分支的历史。
- 如果两个分支的更改在同一文件的同一部分冲突,Git 会标记这些文件,并提示开发者手动解决冲突。
优点:
- 保留了分支的历史,可以清楚地看到何时进行了合并操作。
- 适合团队协作,能方便地管理和整合多条开发线。
缺点:
- 可能会导致多条合并历史,增加 Git 历史的复杂性,尤其是在频繁合并的情况下。
2. git rebase
定义:
git rebase
是将当前分支的基点更改为另一个分支的最新提交。它会将当前分支的提交“移到”目标分支的末尾。工作原理:
- 通过将当前分支的更改逐个应用到目标分支,Git 会尽量将历史线性化。
- 如果在重新应用某个提交时发生冲突,Git 会停止并要求开发者解决冲突。
优点:
- 生成更清晰的线性提交历史,使得回溯和理解更容易。
- 避免了合并引入的额外合并提交。
缺点:
- 可能会重写历史,导致在多人协作时出现问题(尤其是在公共分支上)。
- 处理冲突时,可能需要逐个提交进行解决,较为繁琐。
3.实际场景
下面使用节点 a
, b
, c
, d
等等来表示提交。
假设的提交历史
我们从一个初始的提交开始,假设我们有以下的提交历史:
A -- B -- C (main)
1. 使用 git merge
现在假设我们创建了一个特性分支 feature
,并在这个分支上进行了两次提交 D
和 E
:
A -- B -- C (main)
\
D -- E (feature)
现在我们希望将 feature
分支的更改合并回 main
分支。我们可以执行 git merge feature
,结果如下:
# 切换到 main 分支
git checkout main
# 执行合并
git merge feature
合并后,提交历史会变成:
A -- B -- C ------ M (main)
\ /
D -- E (feature)
M
是合并提交,表示main
分支和feature
分支的历史合并。- 历史保留了两个分支的提交(
C
,D
,E
),并且形成了一个分支图。
2. 使用 git rebase
如果我们选择在特性分支上使用 git rebase
,我们首先会将 main
分支的更新应用到 feature
分支上,然后再将 feature
分支合并回 main
。假设在 feature
分支上我们做了提交 D
和 E
之后,main
分支又有了新的提交 F
:
A -- B -- C -- F (main)
\
D -- E (feature)
在这种情况下,我们执行 git rebase main
:
# 切换到 feature 分支
git checkout feature
# 执行 rebase
git rebase main
变基后,提交历史变成:
A -- B -- C -- F -- D' -- E' (feature)
- 提交
D
和E
被重新应用为D'
和E'
,它们有新的哈希值,因为它们的父提交发生了变化。 feature
分支的历史变得线性了。
接下来,如果我们将 feature
分支合并到 main
:
# 切换到 main 分支
git checkout main
# 合并 feature
git merge feature
最终的提交历史如下:
A -- B -- C -- F -- D' -- E' (main)
4.通俗理解
git rebase
:将自己的开发分支的提交“移到”主分支后面,历史记录被重写为线性(原有分支看似被丢弃,但实际上是重写的)。git merge
:在合并过程中保留自己提交的分支历史,生成一个新的合并提交,清晰地显示出合并后的代码状态。
- 感谢你赋予我前进的力量