引言
在我们日常工作中 项目一般都是团队合作 所以我们大多数接触到的项目都是采用Git进行代码版本控制。在我们使用Git操作代码版本的过程中会遇到很多问题。每次遇到这些问题时,我们通常需要上网查找解决方案。今天我来大概记录下平常我们使用Git过程中所遇到的问题以及解决方案。以便后面遇到我们可以直接代入命令解决处理。
1. 如何撤销工作区中的修改?
工作区指的就是我们新增或者正在编辑的文件,也就是我们日常开发的代码文件。
常见场景:
如果我们修改了某个文件的内容,但又想丢弃掉这些修改,恢复到最近一次提交的状态,可以使用以下命令:
解决步骤:
-
撤销某个文件的修改:
git checkout -- <文件名>
- 这个命令会把指定文件的内容恢复到上次提交时的状态,丢弃掉在工作区的所有修改。
-
撤销所有文件的修改:
git checkout -- .
这个命令会将所有文件的修改都恢复到最近一次提交时的状态。
如果我们平常使用编辑器自带的git功能来操作文件的话,比如我日常工作中一般都是使用编辑器集成的Git插件来操作的 使用编辑器回滚工作区的修改方式比如是这样的:
注意:这个操作会丢弃所有未提交的修改,恢复到上次提交的内容,不可恢复!!!。我们在操作这个命令的时候 一定要确认是否真的不需要保留这些修改。
2. 如何撤销暂存区中的修改?
暂存区就是我们把工作区修改后的文件,使用 git add <文件名>
命令时,文件的修改就会被放入暂存区,表示它们已经准备好提交。简单来说,暂存区就像一个“待提交区”,我们可以在这里准备好哪些修改要纳入到下一次提交中。
常见场景:
假如我们修改的某个文件已经使用 git add
命令提交到暂存区,但我们又想丢弃该文件的修改,该如何操作呢?下面是解决方案:
解决步骤:
-
撤销某个文件在暂存区的修改(使用
git reset
或git restore
):-
使用
git reset HEAD <文件名>
:这个命令会将指定的文件从暂存区移除,但文件的修改会保留在工作区中。换句话说,它撤销了
git add
操作,但并不会影响文件的实际内容。git reset HEAD <文件名>
例如,如果我们修改了
register.vue
文件并且已经git add
,但是现在想撤销暂存区的修改,可以执行:git reset HEAD src/views/register.vue
-
使用
git restore --staged <文件名>
:这个命令与
git reset
命令的作用类似,也是将文件从暂存区移除,保留工作区中的修改。git restore
是Git 2.23以后引入的命令,它的语义更明确,表示“恢复”文件的暂存状态。git restore --staged <文件名>
例如,要撤销
register.vue
文件的暂存,可以运行:git restore --staged src/views/register.vue
-
-
撤销所有文件在暂存区的修改:
如果我们想撤销所有已暂存的文件,可以使用以下命令:
-
使用
git reset HEAD .
:这将把所有暂存的文件从暂存区移除,但文件的修改仍然保留在工作区中。
git reset HEAD .
-
使用
git restore --staged .
:这会撤销所有暂存文件的修改,保留工作区的内容。
git restore --staged .
-
小结:
git reset HEAD <文件名>
和git restore --staged <文件名>
都能将文件从暂存区移除,但文件的修改仍会保留在工作区中。我们可以根据自己的习惯和需要选择其中之一。git reset
是传统的命令,通常用于“重置”暂存区的状态。git restore
是Git 2.23引入的命令,语义更明确,通常用于“恢复”文件的暂存状态。
3. Git commit 提交到仓库后遇到问题怎么解决?
在我们提交到仓库后,可能会遇到各种问题,比如提交信息错误、漏提交、提交到错误分支、甚至需要撤销提交等。以下是每种问题的解决方法:
1. 提交信息错误
假如我们把暂存区的文件使用git命令commit之后我们发现我们的commit信息填写有误需要重新修改该怎么解决呢?
-
未推送到远程仓库的情况:
如果提交信息错误,还没有推送到远程仓库,可以直接使用以下命令修改最近一次提交的信息:
-
使用编辑器修改提交信息:
git commit --amend
执行该命令后,Git 会打开默认的编辑器,允许我们重新修改最近一次提交的信息。修改完成后保存并退出即可。
-
直接在命令行修改提交信息:
git commit --amend -m "新提交信息"
如果不想进入编辑器修改,也可以直接在命令行中输入新的提交信息,
"新提交信息"
是我们想要替换的提交描述。比如我们提交了某个文件 commit信息如下:
我们需要把commit信息改成测试111(图中commit信息皆为测试用 不规范 勿喷哈)。
我们使用命令来修改后如下:
我们修正commit信息后 保存并退出会看到 最新的commit信息:
此时我们再次查看git 提交历史记录会发现已经修改成功:
当然如果我们习惯使用编辑器的话 我们可以这样操作:
我们直接在输入框里面修正我们需要的commit信息点击ok即可:
-
已推送到远程仓库的情况:
如果错误的提交已经推送到远程仓库,我们可以按照以下步骤修改提交信息并强制推送:
git commit --amend git push --force
注意:
强制推送会覆盖远程分支的历史,可能会影响其他团队成员的工作。在团队协作中,请务必与团队成员沟通后再执行此操作。
2. 漏提交文件
假如当我们commit一次暂存区的文件后 我们发现有文件遗漏的情况,通常有两种解决方法:重新创建一个新的 commit 或 修改原先的 commit。
1. 重新创建一个新的 commit
这种方法不会修改原有的提交,而是通过创建一个新的提交将遗漏的文件或修改补充进去。适用于团队协作场景,避免修改历史记录。
操作步骤:
-
将遗漏的文件添加到暂存区:
git add <漏提交的文件>
或者添加所有文件:
git add .
-
创建一个新的提交,补充提交遗漏的内容:
git commit -m "补充提交遗漏的文件"
2. 在原先的 commit 上修改
这种方法会将遗漏的内容直接补充到最近的一次提交中,并修改该提交。适用于本地开发场景,或者推送远程前清理提交历史的情况。
操作步骤:
-
将遗漏的文件添加到暂存区:
git add <漏提交的文件>
或者添加所有遗漏的文件:
git add .
-
使用编辑器修改提交信息:
git commit --amend
执行该命令后,Git 会打开默认的编辑器,允许我们重新修改最近一次提交的信息。修改完成后保存并退出即可。
-
直接在命令行修改提交信息:
git commit --amend -m "新提交信息"
如果不想进入编辑器修改,也可以直接在命令行中输入新的提交信息,
"新提交信息"
是我们想要替换的提交描述。 -
如果我们只需要更新最近的提交内容,同时保留原提交信息:
git commit --amend --no-edit
--no-edit
表示 只修改最近一次提交的内容,但不更改提交信息。
4.提交到错误的分支:如何撤回重新提交
当我们发现提交到了错误的分支后,那么我们需要撤回提交并重新提交到正确的分支。我们可以选择使用 git reset
或 git revert
,具体取决于是否已经推送到远程仓库,以及是否需要保留提交历史。
1. 使用 git reset
撤回提交
git reset
是一种直接修改提交历史的方法。它会将提交记录移除,可以选择是否保留提交的内容。
适用场景:
- 提交 尚未推送到远程仓库。
- 需要完全移除错误的提交记录(不会留下回退的痕迹)。
- 不适合团队协作,尤其是在提交已经被推送到远程时,因为它会破坏分支历史。
三种模式详解
1. git reset --soft HEAD~1
-
功能:
- 仅撤回提交记录(版本库),但保留暂存区和工作区的内容。
- 用于撤销提交后,直接重新提交(包括补充遗漏文件或修改提交信息)。
-
操作步骤:
-
撤回最近一次提交:
git reset --soft HEAD~1
-
根据需要修改或补充文件,然后重新提交:
git commit -m "新的提交信息"
-
-
适用场景:
- 撤销提交后需要补充遗漏内容或修正提交信息。
-
举例:
比如某个场景下我们有个需求修改修改一个文件,正常情况是我们在主分支上面创建一个新的分支用于修改新的文件,但是我们先修改完文件了 但是忘了创建分支了 结果提交到主分支上面了(正常主分支都会设置为保护分支的 这里仅为测试),如下图
这时候我们需要撤回commit提交 但是我们只是为了重新提交到正确的开发分支上面 我们需要保留暂存区和工作区的内容 那么我们就使用以下命令撤回:
git reset --soft HEAD~1
我们可以看到 我们主分支上面的commit记录已经没了 而且文件还在暂存区 这样领导也不会发现我们的骚操作了。然后我们就可以切换到我们需要提交的开发分支进行操作啦。
2. git reset --mixed HEAD~1
(默认)
-
功能:
- 撤回提交记录,并清空暂存区内容,但保留工作区的修改。
- 用于撤销提交后,重新整理并选择性提交文件。
-
操作步骤:
-
撤回最近一次提交,并清空暂存区:
bash git reset HEAD~1
说明:
--mixed
是默认参数,可以省略。 -
如果需要重新提交部分文件,重新将文件添加到暂存区:
git add <文件名>
-
提交修改:
git commit -m "正确的提交信息"
-
-
适用场景:
- 撤销提交后,选择性地重新整理文件内容。
-
举例:
比如某个场景下我们 把修改好的文件提交到了一个错误的分支上面 或者 我们提交到了该分支后 我们发现漏掉了一个文件。如果我们重新提交一次的话 不就暴露自己粗心的性格了嘛。 这时候我们就可以用这个命令进行撤回 而且连带我们暂存区的文件都撤回 这样我们就可以重新整理需要提交的文件内容并且提交了。 这里就不贴图举例了哈。
3. git reset --hard HEAD~1
-
功能:
- 完全撤回提交记录,并清空暂存区和工作区的所有修改。
- 用于彻底恢复到某个版本,适用于不需要保留任何修改的场景。
-
操作步骤:
-
撤回最近一次提交,并清除所有更改:
git reset --hard HEAD~1
-
如果需要回退到特定版本,通过提交 ID 回退:
git reset --hard <commit_id>
说明: 提交 ID 可以通过
git log
查看。
-
-
适用场景:
- 想要完全撤销最近的提交,并清空所有未提交的更改。
-
举例:
- 这里我不举例 因为我基本上不用 谁用谁后悔。。。
小结:git reset
的三种模式
命令 | 版本库 | 暂存区 | 工作区 | 适用场景 |
---|---|---|---|---|
git reset --soft HEAD~1 | 回退 | 不变 | 不变 | 撤销提交,但保留所有修改和暂存内容,用于重新提交或补充内容。 |
git reset --mixed HEAD~1 | 回退 | 清空 | 不变 | 撤销提交,同时移除暂存区内容,但保留工作区修改,用于重新整理文件后提交。 |
git reset --hard HEAD~1 | 回退 | 清空 | 清空 | 完全撤销提交并清除所有修改,恢复到指定版本(破坏性操作,请谨慎使用)。 |
注意事项
-
未推送到远程的场景:
- 可以安全使用
git reset
(尤其是--soft
和--mixed
),根据需要选择保留或移除暂存区和工作区的内容。
- 可以安全使用
-
已推送到远程的场景:
- 不建议使用
git reset
,因为它会修改提交历史,破坏远程分支的完整性。此时推荐使用git revert
。
- 不建议使用
-
误操作恢复:
-
如果误用了
--hard
,可以通过git reflog
找回被删除的提交记录:git reflog git reset --hard <commit_id>
-
比如我们当前的提交记录是这样的:
现在我要撤回最新的那个提交记录 我就使用git reset HEAD~1命令进行撤回: 但是我操作后 由于我操作失误 我多执行了一次 导致上上个操作记录测试333也没了。 这种情况下我就可以用上面的命令进行恢复:
从下图可以看到我们连续撤回了两个提交。现在我们需要恢复上上个提交 我们就可以使用命令 git reset --hard <commit_id> 进行恢复
2. 使用 git revert
撤回提交
git revert
是一种安全的方法,用于撤销提交。它通过创建一个新的提交,将指定的提交内容反向操作,从而撤销原来的更改。提交历史不会被修改,但提交记录中会有一条“撤销”的提交。
适用场景:
- 提交 已经推送到远程仓库。
- 团队协作场景,避免破坏分支历史。
- 不想移除历史记录,只需要在当前分支上撤销提交的内容。
操作步骤:
-
撤销错误分支上的提交:
-
使用以下命令生成一个新的提交,用于撤销指定的提交:
git revert <commit-id>
解释:
commit-id
是需要撤销的提交的哈希值,可以通过git log
查看。- 这会创建一个新的提交,用于撤销指定提交的更改。
-
-
撤销最近一次提交
-
如果需要撤销最近一次的提交,可以使用以下命令:
git revert HEAD
-
-
撤销前前一次提交
-
如果需要撤销前前一次提交(即
HEAD^
指向的提交),可以使用以下命令:git revert HEAD^
-
-
推送更新到远程仓库:
-
推送错误分支的回退记录到远程:
git push origin <错误的分支名>
-
-
将提交内容复制到正确的分支:
-
切换到正确的分支:
git checkout <正确的分支名>
-
使用
git cherry-pick
将错误分支的提交复制到正确的分支:git cherry-pick <commit-id>
-
-
推送正确分支的提交:
git push origin <正确的分支名>
示例:
假设我们误将提交推送到了分支 feature-a
,而应该提交到 feature-b
:
# 撤销错误分支的提交
git revert <commit-id>
# 推送撤销记录
git push origin feature-a
# 切换到正确分支
git checkout feature-b
# 将提交复制到正确的分支
git cherry-pick <commit-id>
# 推送正确分支的更新
git push origin feature-b
我们可以看到操作此命令后,此次操作之前和之后的commit和history都会保留,并且会把这次撤销作为一次最新的提交。
git reset
和 git revert
的对比
命令 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
git reset | 提交尚未推送到远程仓库 | - 简单直接,清除错误提交记录 - 可保留修改,重新提交 | - 破坏历史记录,不适合已推送到远程的场景 - 影响团队协作 |
git revert | 提交已推送到远程仓库 | - 提交历史安全,生成新的提交记录 - 适合团队协作 | - 操作复杂,撤销后需要额外将内容复制到正确分支 |
- 如果提交 尚未推送到远程仓库,推荐使用
git reset
。 - 如果提交 已经推送到远程仓库,推荐使用
git revert
,避免破坏历史记录,适合团队协作。 - 在协作场景下,尽量避免使用
git reset
和强制推送(git push --force
)。
最后
上面我们讲了几个日常工作中比较常遇到的 Git 操作场景问题以及解决方案。虽然我们可以通过这些方法亡羊补牢,但更重要的是在实际工作中养成良好的使用习惯。在使用 Git 提交代码时,一定要仔细检查,确保提交内容正确无误,尤其是在团队协作时,我们更要谨慎操作,避免提交错误信息、推送错误分支或覆盖远程历史等问题。这些问题不仅会影响开发效率,还可能导致团队成员的代码冲突或数据丢失。一定要小心谨慎哈。