Git常用功能
目录
- [🔔 拉取(Pull)与获取(Fetch)](#🔔 拉取(Pull)与获取(Fetch))
- [🔔 重置(reset)](#🔔 重置(reset))
- [🔔 贮藏(stash)](#🔔 贮藏(stash))
- [🔔 补丁(patch)](#🔔 补丁(patch))
- [🔔 摘取(cherry-pick)](#🔔 摘取(cherry-pick))
- [🔔 追溯(Blame)](#🔔 追溯(Blame))
- [🔔 忽略(ignore)](#🔔 忽略(ignore))
🔔 拉取(Pull)与获取(Fetch)
拉取 (Pull)和获取(Fetch)都是用于从远程仓库获取更新的代码。
🔎主要区别:
-
📄
git fetch
(获取): 只下载远程仓库的更新,但不合并到当前分支。它是一个安全的命令,允许你在合并前检查更新内容。 -
📄
git pull
(拉取): 下载远程仓库的更新,并立即合并到当前分支。实际就是git fetch
和git merge
的组合。这一步骤更为直接,但如果远程更新与本地修改有冲突,可能会引发合并冲突。
🔎使用场景:
- 📄
git fetch
(获取): 在多人协作开发时,当你想要了解远程仓库的最新状态,但还不想立即合并这些更新时使用获取
是个好主意。你可以在合并前先评估哪些更改将被引入,确保你的更改不会与其他人的工作产生冲突。 - 📄
git pull
(拉取): 当你已经准备好将远程仓库的更新合并到当前分支时,使用拉取
可以节省一些步骤,因为它会自动执行获取和合并操作。一般在独立维护某个属于你的分支时可以使用。
🔎选项(Option):
📄项目 | 📜格式 | 💡含义 |
---|---|---|
标签 Tags |
git fetch --tags origin git pull --tags origin branch-name | 获取/拉取时同步远程仓库的标签信息。 |
修剪 Prune |
git fetch --prune origin git pull --prune origin branch-name | 获取/拉取之前,删除本地已经不存在的远程分支。 |
下载后运行变基 Rebase after Fetching |
git pull --rebase orgin branch-name | branch-name 是你想要变基的分支名称,重新把当前的基点移植到branch-name 分支的最新提交上 * 更多内容参考文章《Git中的变基(Rebase)》 |
快进式 Fast-Forward |
git pull --ff-only origin branch-name | 当前分支没有任何新的提交时,远程分支的更新直接在当前分支上进行快进: * 意味着当前分支的指针直接移动到远程分支的最新提交点。 * 不会创建新的合并提交。 * 如果当前分支有新的提交导致不能进行快进式合并,操作将失败。 |
非快进式 No-Fast-Forward |
git pull --no-ff origin branch-name | 非快进式合并会强制创建一个新的合并提交: * 即使可以进行快进式合并也会创建。 * 这样可以保留合并历史.。记录更清晰,但会增加提交历史的复杂性 |
不提交 No Commit |
git pull --no-commit origin branch-name | 拉取合并操作完成后,不自动创建提交,而是让用户手动决定何时提交: * 灵活性:在合并完成后,你可以手动检查和修改合并结果 * 灵活性:合并的更改分阶段提交。这对于大规模的更改特别有用,可以让每次提交都更加小巧、易于管理。 * 定制提交信息:可以手动编写提交信息,而不是依赖于Git的默认信息。这对于记录详细的变更历史非常重要。 * 防止错误提交:在合并过程中,如果发现问题,可以在不提交的情况下直接回滚或修复,而不会污染提交历史。 |
🔎Tortoise 示意图:
🔔 重置(reset)
git reset
用于撤销更改和重置仓库的状态。
🔎使用场景:
- 撤销最近的提交。
- 撤销文件的暂存(即从暂存区移除)。
- 将分支指针移动到某个特定的提交。
🔎选项(Option):
📄项目 | 📜格式 | 💡含义 |
---|---|---|
软重置 Soft | git reset --soft HEAD~n | 将HEAD指针移动到前n个提交,保留所有更改在暂存区与工作区中。 |
软重置 Soft | git reset --soft <commit> | 会将HEAD指针移动到指定的提交,但不会改变暂存区和工作目录的内容。 这意味着你所做的更改(包括已经提交的更改)仍然会保留在工作目录和暂存区中。 |
硬重置 Hard | git reset --hard HEAD~n | 将仓库重置到前n提交,所有更改和暂存区的更改将被丢弃。 |
硬重置 Hard | git reset --hard <commit> | 会将HEAD指针移动到指定的提交,暂存区和工作目录都重置到指定的提交。 这意味着所有未提交的更改和暂存的更改都会被删除,工作目录将恢复到指定提交时的状态。 |
混合 Mixed | git reset --mixed HEAD~n | 将HEAD指针移动到前n个提交,并将更改保留在工作目录中,但从暂存区中移除。 |
混合 Mixed | git reset --mixed <commit> | 会将HEAD指针移动到指定的提交,但不会改变工作目录的内容。 这意味着你所做的更改(包括已经提交的更改)仅会保留在工作目录中。 |
🔎Soft Hard和Mixed区别原理图
软重置与混合的区别是:已修改的内容是否会保留在
暂存区
。实际应用中区别不大。
🔎 Tortoise 示意图:
🔔 贮藏(stash)
Git的贮藏功能(
stash
)是一个非常有用的工具,可以临时保存你的工作目录中的未提交更改,并恢复到一个干净的工作状态。贮藏功能允许你在不提交当前更改的情况下切换分支或进行其他操作,稍后再恢复这些更改。
🔎基本用法:
-
📄
git stash
(贮藏当前更改): 将当前工作目录和暂存区的更改保存到一个堆栈中,并恢复到干净的工作状态(与上次提交的状态相同)。默认情况下,git stash 会保存所有未提交的更改(包括暂存的和未暂存的更改)。 -
📄
git stash apply
(恢复贮藏的更改): 将最近贮藏的更改应用到当前工作目录,但不会从贮藏中删除该条目。 -
📄
git stash drop
(删除贮藏条目):删除最近的贮藏条目,或者使用索引删除特定条目。 -
📄
git stash pop
(弹出贮藏条目):这是git stash apply
和git stash drop
的组合将最近的贮藏条目应用到当前工作目录,并从贮藏堆栈中删除。 -
📄
git stash list
(查看贮藏条目):查看所有贮藏的条目。bashgit stash list stash@{0}: WIP on master: 1234567 Commit message stash@{1}: WIP on master: 89abcdef Another commit message
-
📄
git stash push
(贮藏特定更改):贮藏特定的文件或目录的更改。bashgit stash push -m "Stash message" -- path/to/file
❗ 注意:
- 在恢复贮藏的更改时,如果工作目录中有与贮藏更改冲突的更改,Git会报告冲突,你需要手动解决这些冲突。
- 默认情况下,git stash 不会贮藏未跟踪的文件。可以使用 -u 或 --include-untracked 选项包括未跟踪的文件。
- 默认情况下,git stash 不会贮藏被删除的文件。可以使用 -a 或 --all 选项包括所有文件。
🔎 Tortoise 示意图:
- 贮藏
- 贮藏的选项
- 弹出贮藏或者查看贮藏
🔔 补丁(patch)
Git的补丁(patch)功能是一种非常强大的工具,用于在不同代码库之间共享更改,进行代码审查,或者在不直接合并的情况下应用其他分支的更改。补丁功能主要通过
git diff
和git format-patch
命令创建,通过git apply
和git am
命令应用。
🔎基本用法:
-
📄 创建补丁
📜格式示例 💡含义 git diff > my_changes.patch 生成当前工作目录中更改的补丁,输出到一个名为 my_changes.patch
的文件中git format-patch > n_changes.patch -n
HEAD创建 n
个提交的补丁文件,输出到一个名为n_changes.patch
的文件中。 这个文件包含提交的详细信息,包括提交信息、作者信息和更改内容git format-patch origin/main 创建自从 origin/main
分支以来的所有提交的补丁文件 -
📄 应用补丁
📜格式示例 💡含义 git apply my_changes.patch 将 my_changes.patch
中的更改应用到当前工作目录,但不会创建新的提交git am n_changes.patch 用于应用由 git format-patch
生成的补丁文件,并将这些更改作为新的提交添加到当前分支。git am
会保留补丁文件中的提交信息。git am --continue 当应用补丁时,如果目标代码库中的更改与补丁中的更改发生冲突,Git会提示你解决冲突。解决冲突后,继续应用补丁 git am --abort 中止应用补丁
🔎 git format-patch
与git diff
的区别:
git format-patch
: 用于生成包含提交信息的补丁文件,适合共享完整的提交记录。git diff
: 用于生成仅包含代码更改的补丁文件,适合共享特定范围内的更改而不包含提交信息。
🔎 Tortoise 示意图:
- 创建补丁
- 创建特定文件的补丁
. - 应用补丁
打开diff
补丁文件,点击文件
,点击应用补丁
,选择需要应用的工程项目:
🔔 摘取(cherry-pick)
Git的摘取
(cherry-pick)
功能允许你将某个分支中的特定提交应用到另一个分支,而无需合并整个分支。这个功能在需要引入特定更改而不是合并整个开发历史时非常有用。
🔎基本用法:
-
📄 单个提交的摘取:
<commit-hash>
是需要摘取的提交的hash值bashgit cherry-pick <commit-hash>
-
📄 多个提交的摘取:
bashgit cherry-pick <commit-hash-1> <commit-hash-2> ...
🔎选项(Option):
📄项目 | 📜格式 | 💡含义 |
---|---|---|
编写提交消息 -e 或--edit |
git cherry-pick --edit <commit-hash> git cherry-pick -e <commit-hash> | 默认情况下,摘取会使用原始提交的提交信息。 使用 -e 或 --edit 选项可以编辑提交信息。 |
不提交 --no-commit |
git cherry-pick --no-commit <commit-hash> | 摘取之后不提交以便手动检查 |
🔎示例:
-
假设你有如下提交历史,你希望将
feature-branch
中的提交C
和D
应用到main
分支:cssA---B---C---D---E (feature-branch) \ F---G---H (main)
-
切换到
main
目标分支,摘取提交:bashgit cherry-pick <commit-hash-C> <commit-hash-D> ...
-
main
分支的历史会变成:cssA---B---F---G---H---'C'---'D' (main) \ C---D---E (feature-branch)
🔎 Tortoise 示意图:
- 进入
日志信息
,选择你要摘取的提交,右键选择摘取此提交
:
- 摘取具体页面:
_
🔔 追溯(Blame)
Git 的追溯功能主要通过
git blame
命令来实现。git blame
用于显示文件的每一行最后一次修改的提交信息,包括提交哈希、作者、日期和行号。这个功能对于代码审查、调试和理解代码变更历史非常有用。
🔎基本用法:
-
📄 显示文件的追溯信息:
shgit blame <file>
🔎选项(Option):
📄项目 | 📜格式 | 💡详解 |
---|---|---|
指定范围 -L |
git blame -L <start>,<end> <file> | 指定文件的行号范围,仅显示该范围内的追溯信息。 例如显示 example.txt 文件的第 1 到第 3 行:git blame -L 1,3 example.txt |
显示更多信息 -p |
git blame -p <file> | 显示更详细的追溯信息,包括每行的作者、日期、提交信息等。 |
忽略空白变化 -w |
git blame -w <file> | 忽略空白字符的变化,如缩进和行尾空格变化。 |
🔎 Tortoise 示意图:
- 右键 要追溯的文件,TortoiseGit ------>追溯 :
- 详细页面:
🔔 忽略(ignore)
Git 的忽略功能通过
.gitignore
文件来实现,允许你指定哪些文件或目录应被 Git 忽略。这在管理大型项目或避免提交敏感文件时非常有用。
.gitignore
文件位于 Git 仓库的根目录或任何子目录中。每个.gitignore
文件定义了相对当前目录的忽略规则。
🔎基本用法:
- 📄 创建
.gitignore
文件:在项目的根目录中创建一个名为.gitignore
的文件
🔎示例:
假设项目的目录结构如下:
project/
├── .gitignore
├── node_modules/
│ ├── hulu.dll
│ └── other.dll
├── dist/
│ └── bundle.js
├── src/
│ ├── main.cc
│ └── main.tmp
├── logs/
│ ├── app.log
│ ├── 1.log
│ └── system.log
├── hulu.txt
├── private/
│ └── private-data.txt
└── tmp/
└── temp.tmp
假设你的.gitignore
如下:
plaintext
# 忽略所有 .exe 文件
*.exe
# 忽略所有 .dll 文件,但不忽略hulu.dll文件
*.dll
!hulu.dll
# 忽略 a.log、b.log等单个字符的.log文件,但不忽略 aa.log这些多个字符的文件
?.log
# 忽略 src 目录下的所有 .tmp 文件,不论其深度
src/**/*.tmp
# 忽略所有 dist 目录及其子目录
dist/
# 忽略tmp目录下的所有文件,但不忽略该目录本身
tmp/*
# 忽略特定文件或目录
hulu.txt
/private/
最终这些文件或目录会被忽略:
other.dll
dist/
1.log
private/
src/main.tmp
tmp/temp.tmp
🔎 Tortoise 示意图:
- 忽略一个文件:
- 忽略一个已跟踪的文件: