日常开发中的 Git 操作问题总结与解决方案

429 阅读15分钟

引言

在我们日常工作中 项目一般都是团队合作 所以我们大多数接触到的项目都是采用Git进行代码版本控制。在我们使用Git操作代码版本的过程中会遇到很多问题。每次遇到这些问题时,我们通常需要上网查找解决方案。今天我来大概记录下平常我们使用Git过程中所遇到的问题以及解决方案。以便后面遇到我们可以直接代入命令解决处理。

1. 如何撤销工作区中的修改?

工作区指的就是我们新增或者正在编辑的文件,也就是我们日常开发的代码文件。

常见场景:

如果我们修改了某个文件的内容,但又想丢弃掉这些修改,恢复到最近一次提交的状态,可以使用以下命令:

解决步骤:

  • 撤销某个文件的修改:

    git checkout -- <文件名>
    
    • 这个命令会把指定文件的内容恢复到上次提交时的状态,丢弃掉在工作区的所有修改。
  • 撤销所有文件的修改:

    git checkout -- .
    

    这个命令会将所有文件的修改都恢复到最近一次提交时的状态。

如果我们平常使用编辑器自带的git功能来操作文件的话,比如我日常工作中一般都是使用编辑器集成的Git插件来操作的 使用编辑器回滚工作区的修改方式比如是这样的:

image.png

image.png

注意:这个操作会丢弃所有未提交的修改,恢复到上次提交的内容,不可恢复!!!。我们在操作这个命令的时候 一定要确认是否真的不需要保留这些修改。


2. 如何撤销暂存区中的修改?

暂存区就是我们把工作区修改后的文件,使用 git add <文件名> 命令时,文件的修改就会被放入暂存区,表示它们已经准备好提交。简单来说,暂存区就像一个“待提交区”,我们可以在这里准备好哪些修改要纳入到下一次提交中。

常见场景:

假如我们修改的某个文件已经使用 git add 命令提交到暂存区,但我们又想丢弃该文件的修改,该如何操作呢?下面是解决方案:

解决步骤:

  1. 撤销某个文件在暂存区的修改(使用 git resetgit restore):

    • 使用 git reset HEAD <文件名>

      这个命令会将指定的文件从暂存区移除,但文件的修改会保留在工作区中。换句话说,它撤销了 git add 操作,但并不会影响文件的实际内容。

      git reset HEAD <文件名>
      

      例如,如果我们修改了 register.vue 文件并且已经 git add,但是现在想撤销暂存区的修改,可以执行:

      git reset HEAD src/views/register.vue
      

      image.png

      image.png

    • 使用 git restore --staged <文件名>

      这个命令与 git reset 命令的作用类似,也是将文件从暂存区移除,保留工作区中的修改。git restore 是Git 2.23以后引入的命令,它的语义更明确,表示“恢复”文件的暂存状态。

      git restore --staged <文件名>
      

      例如,要撤销 register.vue 文件的暂存,可以运行:

      git restore --staged src/views/register.vue
      

      image.png

      image.png

  2. 撤销所有文件在暂存区的修改:

    如果我们想撤销所有已暂存的文件,可以使用以下命令:

    • 使用 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信息填写有误需要重新修改该怎么解决呢?

  • 未推送到远程仓库的情况:

    如果提交信息错误,还没有推送到远程仓库,可以直接使用以下命令修改最近一次提交的信息:

  1. 使用编辑器修改提交信息:

    git commit --amend
    

    执行该命令后,Git 会打开默认的编辑器,允许我们重新修改最近一次提交的信息。修改完成后保存并退出即可。

  2. 直接在命令行修改提交信息:

    git commit --amend -m "新提交信息"
    

    如果不想进入编辑器修改,也可以直接在命令行中输入新的提交信息,"新提交信息" 是我们想要替换的提交描述。

    比如我们提交了某个文件 commit信息如下:

    image.png

    我们需要把commit信息改成测试111(图中commit信息皆为测试用 不规范 勿喷哈)。

    我们使用命令来修改后如下:

    image.png

    我们修正commit信息后 保存并退出会看到 最新的commit信息:

    image.png

    此时我们再次查看git 提交历史记录会发现已经修改成功:

    image.png

    当然如果我们习惯使用编辑器的话 我们可以这样操作:

    image.png

    我们直接在输入框里面修正我们需要的commit信息点击ok即可:

    image.png

  • 已推送到远程仓库的情况:

    如果错误的提交已经推送到远程仓库,我们可以按照以下步骤修改提交信息并强制推送:

    git commit --amend
    git push --force
    

    image.png

    注意: 强制推送会覆盖远程分支的历史,可能会影响其他团队成员的工作。在团队协作中,请务必与团队成员沟通后再执行此操作。

2. 漏提交文件

假如当我们commit一次暂存区的文件后 我们发现有文件遗漏的情况,通常有两种解决方法:重新创建一个新的 commit修改原先的 commit

1. 重新创建一个新的 commit

这种方法不会修改原有的提交,而是通过创建一个新的提交将遗漏的文件或修改补充进去。适用于团队协作场景,避免修改历史记录。

操作步骤:

  1. 将遗漏的文件添加到暂存区:

    git add <漏提交的文件>
    

    或者添加所有文件:

    git add .
    
  2. 创建一个新的提交,补充提交遗漏的内容:

    git commit -m "补充提交遗漏的文件"
    

2. 在原先的 commit 上修改

这种方法会将遗漏的内容直接补充到最近的一次提交中,并修改该提交。适用于本地开发场景,或者推送远程前清理提交历史的情况。

操作步骤:

  1. 将遗漏的文件添加到暂存区:

    git add <漏提交的文件>
    

    或者添加所有遗漏的文件:

    git add .
    
  2. 使用编辑器修改提交信息:

    git commit --amend
    

    执行该命令后,Git 会打开默认的编辑器,允许我们重新修改最近一次提交的信息。修改完成后保存并退出即可。

  3. 直接在命令行修改提交信息:

    git commit --amend -m "新提交信息"
    

    如果不想进入编辑器修改,也可以直接在命令行中输入新的提交信息,"新提交信息" 是我们想要替换的提交描述。

  4. 如果我们只需要更新最近的提交内容,同时保留原提交信息:

    git commit --amend --no-edit
    

    --no-edit 表示 只修改最近一次提交的内容,但不更改提交信息


4.提交到错误的分支:如何撤回重新提交

当我们发现提交到了错误的分支后,那么我们需要撤回提交并重新提交到正确的分支。我们可以选择使用 git resetgit revert,具体取决于是否已经推送到远程仓库,以及是否需要保留提交历史。

1. 使用 git reset 撤回提交

git reset 是一种直接修改提交历史的方法。它会将提交记录移除,可以选择是否保留提交的内容。

适用场景:
  • 提交 尚未推送到远程仓库
  • 需要完全移除错误的提交记录(不会留下回退的痕迹)。
  • 不适合团队协作,尤其是在提交已经被推送到远程时,因为它会破坏分支历史。
三种模式详解

1. git reset --soft HEAD~1

  • 功能:

    • 仅撤回提交记录(版本库),但保留暂存区和工作区的内容。
    • 用于撤销提交后,直接重新提交(包括补充遗漏文件或修改提交信息)。
  • 操作步骤:

    1. 撤回最近一次提交:

      git reset --soft HEAD~1
      
    2. 根据需要修改或补充文件,然后重新提交:

      git commit -m "新的提交信息"
      
  • 适用场景:

    • 撤销提交后需要补充遗漏内容或修正提交信息。
  • 举例:

    比如某个场景下我们有个需求修改修改一个文件,正常情况是我们在主分支上面创建一个新的分支用于修改新的文件,但是我们先修改完文件了 但是忘了创建分支了 结果提交到主分支上面了(正常主分支都会设置为保护分支的 这里仅为测试),如下图

    image.png

    这时候我们需要撤回commit提交 但是我们只是为了重新提交到正确的开发分支上面 我们需要保留暂存区和工作区的内容 那么我们就使用以下命令撤回:

    git reset --soft HEAD~1
    

    image.png

    image.png

我们可以看到 我们主分支上面的commit记录已经没了 而且文件还在暂存区 这样领导也不会发现我们的骚操作了。然后我们就可以切换到我们需要提交的开发分支进行操作啦。

2. git reset --mixed HEAD~1 (默认)

  • 功能:

    • 撤回提交记录,并清空暂存区内容,但保留工作区的修改。
    • 用于撤销提交后,重新整理并选择性提交文件。
  • 操作步骤:

    1. 撤回最近一次提交,并清空暂存区:

      bash
      git reset HEAD~1
      

      说明: --mixed 是默认参数,可以省略。

    2. 如果需要重新提交部分文件,重新将文件添加到暂存区:

      git add <文件名>
      
    3. 提交修改:

      git commit -m "正确的提交信息"
      
  • 适用场景:

    • 撤销提交后,选择性地重新整理文件内容。
  • 举例:

比如某个场景下我们 把修改好的文件提交到了一个错误的分支上面 或者 我们提交到了该分支后 我们发现漏掉了一个文件。如果我们重新提交一次的话 不就暴露自己粗心的性格了嘛。 这时候我们就可以用这个命令进行撤回 而且连带我们暂存区的文件都撤回 这样我们就可以重新整理需要提交的文件内容并且提交了。 这里就不贴图举例了哈。

3. git reset --hard HEAD~1

  • 功能:

    • 完全撤回提交记录,并清空暂存区和工作区的所有修改。
    • 用于彻底恢复到某个版本,适用于不需要保留任何修改的场景。
  • 操作步骤:

    1. 撤回最近一次提交,并清除所有更改:

      git reset --hard HEAD~1
      
    2. 如果需要回退到特定版本,通过提交 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回退清空清空完全撤销提交并清除所有修改,恢复到指定版本(破坏性操作,请谨慎使用)。

注意事项

  1. 未推送到远程的场景:

    • 可以安全使用 git reset(尤其是 --soft--mixed),根据需要选择保留或移除暂存区和工作区的内容。
  2. 已推送到远程的场景:

    • 不建议使用 git reset,因为它会修改提交历史,破坏远程分支的完整性。此时推荐使用 git revert
  3. 误操作恢复:

    • 如果误用了 --hard,可以通过 git reflog 找回被删除的提交记录:

      git reflog
      git reset --hard <commit_id>
      

比如我们当前的提交记录是这样的:

image.png

现在我要撤回最新的那个提交记录 我就使用git reset HEAD~1命令进行撤回: 但是我操作后 由于我操作失误 我多执行了一次 导致上上个操作记录测试333也没了。 这种情况下我就可以用上面的命令进行恢复:

image.png

从下图可以看到我们连续撤回了两个提交。现在我们需要恢复上上个提交 我们就可以使用命令 git reset --hard <commit_id> 进行恢复

image.png

image.png

2. 使用 git revert 撤回提交

git revert 是一种安全的方法,用于撤销提交。它通过创建一个新的提交,将指定的提交内容反向操作,从而撤销原来的更改。提交历史不会被修改,但提交记录中会有一条“撤销”的提交。

适用场景:
  • 提交 已经推送到远程仓库
  • 团队协作场景,避免破坏分支历史。
  • 不想移除历史记录,只需要在当前分支上撤销提交的内容。
操作步骤:
  1. 撤销错误分支上的提交:

    • 使用以下命令生成一个新的提交,用于撤销指定的提交:

      git revert <commit-id>
      

    解释:

    • commit-id 是需要撤销的提交的哈希值,可以通过 git log 查看。
    • 这会创建一个新的提交,用于撤销指定提交的更改。
  2. 撤销最近一次提交

    • 如果需要撤销最近一次的提交,可以使用以下命令:

      git revert HEAD
      
  3. 撤销前前一次提交

    • 如果需要撤销前前一次提交(即 HEAD^ 指向的提交),可以使用以下命令:

      git revert HEAD^
      
  4. 推送更新到远程仓库:

    • 推送错误分支的回退记录到远程:

      git push origin <错误的分支名>
      
  5. 将提交内容复制到正确的分支:

    • 切换到正确的分支:

      git checkout <正确的分支名>
      
    • 使用 git cherry-pick 将错误分支的提交复制到正确的分支:

      git cherry-pick <commit-id>
      
  6. 推送正确分支的提交:

    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

image.png

我们可以看到操作此命令后,此次操作之前和之后的commit和history都会保留,并且会把这次撤销作为一次最新的提交。

git resetgit revert 的对比

命令适用场景优点缺点
git reset提交尚未推送到远程仓库- 简单直接,清除错误提交记录 - 可保留修改,重新提交- 破坏历史记录,不适合已推送到远程的场景 - 影响团队协作
git revert提交已推送到远程仓库- 提交历史安全,生成新的提交记录 - 适合团队协作- 操作复杂,撤销后需要额外将内容复制到正确分支
  • 如果提交 尚未推送到远程仓库,推荐使用 git reset
  • 如果提交 已经推送到远程仓库,推荐使用 git revert,避免破坏历史记录,适合团队协作。
  • 在协作场景下,尽量避免使用 git reset 和强制推送(git push --force)。

最后

上面我们讲了几个日常工作中比较常遇到的 Git 操作场景问题以及解决方案。虽然我们可以通过这些方法亡羊补牢,但更重要的是在实际工作中养成良好的使用习惯。在使用 Git 提交代码时,一定要仔细检查,确保提交内容正确无误,尤其是在团队协作时,我们更要谨慎操作,避免提交错误信息、推送错误分支或覆盖远程历史等问题。这些问题不仅会影响开发效率,还可能导致团队成员的代码冲突或数据丢失。一定要小心谨慎哈。