Skip to content

Git工作区域

Git 有三个主要的工作区域:

  1. 工作区(Working Directory):你在电脑上看到的目录,用于保存项目的实际文件。
  2. 暂存区(Staging Area):也叫索引(Index),是一个临时区域,保存了下一次提交所要包含的文件修改信息。
  3. 版本库(Repository):工作区的一个隐藏目录 .git,是 Git 的核心部分,包含了项目所有的版本记录。

在 Git 的工作流程中,你的修改首先会被保存在工作区,之后你需要将它们添加到暂存区以便下一次提交时可以包含这些修改。使用 git add 命令将修改添加到暂存区。最后,使用 git commit 命令将暂存区中的修改提交到版本库。

如果在工作区中对文件进行了修改,但没有使用 git add 命令将修改添加到暂存区,那么这些修改不会被包含在下一次提交中。

如果你已经将修改添加到了暂存区,但想要撤销暂存,也就是不将修改包含在下一次提交中,可以使用 git reset 命令。

如果你已经将修改提交到版本库,但后悔了这次提交,可以使用 git resetgit revert 命令来撤销提交。但是这两个命令的使用方式和效果略有不同。

提交规范

php
<type>(<scope>): <subject>

<body>

<footer>

1.type 表示提交的类型,scope 表示更改的范围,subject 是一句简洁的描述,body 是更详细的描述,footer 则用于添加与提交相关的元数据。

2.使用规范的提交类型:提交类型应该是明确的,以便其他开发者能够轻松地理解更改的性质。以下是一些常见的提交类型:

  • feat:新功能
  • fix:修复问题
  • docs:文档更新
  • style:样式更新
  • refactor:重构代码
  • test:测试更新
  • perf:性能优化
  • chore:构建过程或辅助工具的变更

基本指令

git init:初始化一个 Git 仓库。
git clone:从远程仓库克隆代码到本地。
git add:将文件添加到 Git 索引中
git restore --staged <文件> :取消暂存
git restore <文件> :丢弃工作区的修改
git commit:提交代码更改到本地仓库。
git push:将本地仓库的代码推送到远程仓库。
git pull:从远程仓库拉取最新代码到本地。
git branch:列出所有本地分支。
git checkout:切换分支或恢复文件。
git merge:合并指定分支到当前分支。
git status:显示当前仓库的状态。
git log:查看提交历史。
git log --oneline :简洁的提交历史
git diff:查看文件之间的差异。
git stash:贮藏。
git stash: 将当前的修改保存到一个新的 stash 中。
git stash save "<message>": 将当前的修改保存到一个新的 stash 中,并附带一条消息。
git stash list: 显示当前所有的 stash 列表。
git stash apply: 应用最近的 stash,并将其保留在 stash 列表中。
git stash apply stash@{n}: 应用指定的 stash,并将其保留在 stash 列表中。
git stash pop: 应用最近的 stash,并将其从 stash 列表中移除。
git stash pop stash@{n}: 应用指定的 stash,并将其从 stash 列表中移除。
git stash drop: 移除最近的 stash,但不应用其修改。
git stash drop stash@{n}: 移除指定的 stash,但不应用其修改。
git stash clear: 移除所有的 stash,但不应用任何修改。
git stash -m 贮藏并添加备注
git tag:创建、列出或删除标签。
git remote:管理远程仓库。

组合指令

git checkout . : # 撤销对所有已修改但未提交(未暂存,暂存的文件无法撤销)的文件的修改,但不包括新增的文件
git checkout -b feature :创建一个名为 feature 的新分支并立即切换到该分支
git push --set-upstream origin feature === git push -u origin feature :用于将本地新建的分支 feature 推送到远程仓库,并将其与远程仓库中同名的分支建立关联关系。其中-u为--set-upstream缩写
git reset:回退版本

git reset: 命令用于将当前分支的 HEAD 指针重置为指定的提交,同时将暂存区和工作区的文件恢复到重置后的状态。

具体用法如下:

  • git reset: 把所有已暂存的文件恢复到未暂存的状态。此时你可以使用 git status 命令查看文件状态,确认文件已恢复到未暂存状态。

  • git reset <commit>:将 HEAD 指针重置为指定的提交,不影响暂存区和工作区的文件;

解释一:

  • git reset --soft <commit>:将 HEAD 指针重置为指定的提交,同时将暂存区的文件恢复到重置后的状态,但不影响工作区的文件;—— 就是重置后将当前版本之后的改动添加到暂存区 重置commit -> 保留暂存区
  • git reset --mixed <commit>:将 HEAD 指针重置为指定的提交,同时将暂存区和工作区的文件恢复到重置后的状态;—— 就是在soft的基础上将暂存区的文件恢复到未暂存状态 重置commit -> 重置暂存区 -> 保留未暂存区(工作区)
  • git reset --hard <commit>:将 HEAD 指针重置为指定的提交,同时将暂存区和工作区的文件恢复到重置后的状态,并且不可恢复地清除之前的提交记录。——就是没有保留本版本之后的状态,重置工作区

解释二:

  • git reset --soft commit:重置 HEAD 指针为指定提交,但是不重置暂存区和工作区。也就是说,之前 git commit 的内容会被撤销,但是暂存区和工作区的修改都会被保留。
  • git reset --mixed commit:重置 HEAD 指针和暂存区为指定提交,但是不重置工作区。也就是说,之前 git add 的内容会被撤销,但是不会删除工作区修改的内容。
  • git reset --hard commit:重置 HEAD 指针、暂存区和工作区为指定提交,也就是彻底撤销之前的提交,包括之前的 git addgit commit

因此,--mixed 选项会重置暂存区,而 --hard 选项会重置工作区和暂存区。而 --soft 选项不会重置暂存区和工作区,只是撤销之前的提交。

在实际应用中,git reset 常用于撤销某些提交,并将之后的提交合并到一个新的提交中,以清除不必要的历史记录。

git reset commitgit reset --mixed commit 是等效的。如果不指定 --mixed--soft--hard 参数,则默认使用 --mixed 参数。--mixed 参数会将 Git 仓库中的 HEAD 指针和暂存区同时重置为指定提交,但不会改变工作区,也就是不会修改实际文件。因此,这个操作会撤销上一次的 git add 操作,但不会丢失修改。

所以,下面两个命令是等效的:

git reset commit
git reset --mixed commit
git revert:撤销提交

git revert 命令用于创建一个新的提交,该提交的内容与指定的提交相反,即撤销指定提交的修改。

具体用法如下:

  • git revert <commit>:撤销指定提交的修改,并创建一个新的提交。

git revert 命令实际上是通过创建新的提交来撤销之前的提交,因此它不会改变已有的提交历史记录,也不会影响其他人的工作。但是,由于需要创建新的提交,因此会增加提交历史记录的复杂度。

git revert命令用于撤销之前的提交,它会创建一个新的提交来撤销指定的提交内容。关于同文件和不同文件的区别,让我为您解释一下:
  1. 同文件的情况: 当您使用git revert来撤销某个提交,而且这个提交修改了一个或多个文件,git revert会尝试将被撤销提交中所做的更改还原到当前分支中。这意味着,被撤销的文件将回到之前提交的状态,但是这个过程会在一个新的提交中进行。如果您在之前的提交中修改了文件A,并且使用git revert来撤销这个提交,那么文件A将被还原到之前的状态,并且会创建一个新的提交来记录这次还原。
  2. 不同文件的情况: 如果您的历史中包含了多个提交,其中有些修改了文件A,而其他提交修改了文件B,C等等,如果您使用git revert来撤销一个修改文件A的提交,那么只有文件A会被还原到之前的状态,并且会创建一个新的提交。其他文件(如B、C等)不会受到影响,它们的状态不会改变。

总之,git revert是一个非破坏性的操作,它通过创建新的提交来撤销指定的提交,因此您可以在不影响其他开发者或分支的情况下撤销变更。如果您想撤销多个提交,您可以按照需要多次使用git revert命令。

Merge + Fast-Forward(快转合并模式)

**快转合并的要求 **

Fast-Forward 合并是一种特殊的合并情况,在这种情况下,Git 可以直接将目标分支移动到要合并的分支的最新提交上,而不需要创建新的合并提交。要执行 Fast-Forward 合并,需要满足以下要求:

  1. 目标分支与要合并的分支之间没有新的提交: 如果目标分支(通常是主分支)和要合并的分支之间没有新的提交,即目标分支不落后于要合并的分支,那么就可以执行 Fast-Forward 合并。
  2. 要合并的分支是目标分支的直接上游分支: 要合并的分支(通常是特性分支)必须是目标分支的直接上游分支。也就是说,要合并的分支是从目标分支分出来的,没有经过其他分支的合并。

如果满足了以上两个要求,Git 将会执行 Fast-Forward 合并,直接将目标分支指向要合并的分支的最新提交,从而完成合并操作。这种合并方式可以保持分支历史记录的整洁和简单,因为不会产生额外的合并提交。

示例1:满足 Fast-Forward 合并条件

假设有两个分支:main 分支和 feature 分支。

  • main 分支是目标分支,它是我们要将修改合并到的分支。
  • feature 分支是要合并的分支,它包含了我们在开发过程中所做的修改。

假设在执行合并操作之前,main 分支和 feature 分支的提交历史如下:

mathematica
main 分支:    A --- B (HEAD)
                
feature 分支:        \
                      C --- D (HEAD)

在这种情况下,如果 main 分支和 feature 分支之间没有新的提交,且 feature 分支是从 main 分支分出来的,那么满足 Fast-Forward 合并条件。此时执行合并操作,Git 将直接将 main 分支指向 feature 分支的最新提交,不需要创建新的合并提交:

mathematica
main 分支:    A --- B --- C --- D (HEAD)

feature 分支:                \
                              C --- D

示例2:不满足 Fast-Forward 合并条件

继续以上示例,如果在执行合并操作之前,main 分支有新的提交,那么就不再满足 Fast-Forward 合并的条件了。

假设此时 main 分支的提交历史如下:

mathematica
main 分支:    A --- B --- E (HEAD)
                
feature 分支:        \
                      C --- D

在这种情况下,main 分支和 feature 分支之间有新的提交 E,因此不满足 Fast-Forward 合并的条件。此时无法直接将 main 分支指向 feature 分支的最新提交,需要创建一个新的合并提交来整合两个分支的修改。

mathematica
main 分支:    A --- B --- E --- M (HEAD)
                           /       \
feature 分支:             C --- D ---/

Released under the MIT License.