关于git:如何修改现有的未提交的提交?

How to modify existing, unpushed commits?

我在提交消息中写错了东西。或者,我忘了包含一些文件。

如何更改提交消息/文件?提交尚未被推送。


修改最新的提交消息

1
git commit --amend

将打开编辑器,允许您更改最近提交的提交消息。此外,可以在命令行中直接使用以下命令设置提交消息:

1
git commit --amend -m"New commit message"

…但是,这可能会使多行提交消息或小的更正更难输入。

在执行此操作之前,请确保没有任何工作副本更改,否则它们也将被提交。(未保存的更改将不会被提交。)

更改已推送到远程分支的提交消息

如果已经将提交推送到远程分支,则需要使用以下命令强制推送提交:

1
2
3
git push <remote> <branch> --force
# Or
git push <remote> <branch> -f

警告:强制推将使用本地分支的状态覆盖远程分支。如果远程分支上有您在本地分支中没有的提交,那么您将丢失这些提交。

警告:请注意修改您已经与其他人共享的承诺。修改提交实质上重写了它们,使它们具有不同的shaid,如果其他人拥有您重写的旧提交的副本,则会造成问题。任何拥有旧提交副本的人都需要将他们的工作与您新重新编写的提交同步,这有时可能很困难,因此在尝试重写共享提交历史记录时,请确保与其他人协调,或者避免完全重写共享提交。

使用交互式钢筋网

另一种选择是使用交互式钢筋网。这允许您编辑任何要更新的消息,即使它不是最新的消息。

要进行Git挤压,请执行以下步骤:

1
2
// X is the number of commits to the last commit you want to be able to edit
git rebase -i HEAD~X

一旦你取消了你的承诺——选择e/r来编辑消息。

enter image description here

关于交互式钢筋的重要说明

当您使用git rebase -i HEAD~X时,可能有多个X提交。Git将"收集"上一次X提交中的所有提交,如果在该范围内的某个地方进行合并,您将看到所有提交,因此结果将是x+。

好提示:

如果您需要为多个分支执行此操作,并且在修改内容时可能会遇到冲突,请设置git rerere,并让git自动为您解决这些冲突。

文档

  • Git提交(1)手册页

  • Git Rebase(1)手册页

  • Git Push(1)手册页


1
git commit --amend -m"your new message"


如果要修复的提交不是最新的提交:

  • git rebase --interactive $parent_of_flawed_commit

    如果要修复多个有缺陷的提交,请传递其中最旧的一个提交的父级。

  • 会有一个编辑器出现,列出自您给出的提交以来的所有提交。

  • 在您要修复的任何承诺之前,将pick更改为reword(或在Git的旧版本上,更改为edit)。
  • 保存后,Git将重放列出的提交。
    BR/>
  • 对于您要改写的每个提交,Git都会将您放回编辑器中。对于您要编辑的每个提交,git都会将您放入shell。如果你在空壳里:

  • 以任何你喜欢的方式改变承诺。
  • git commit --amend
  • git rebase --continue
  • 这个序列中的大部分将通过在执行过程中输出各种命令来向您解释。这很容易,你不需要记住它——只要记住git rebase --interactive允许你纠正承诺,不管它们多久以前。

    请注意,您将不希望更改已推送的提交。或者你可能会这样做,但在这种情况下,你必须非常小心地与每个可能已经完成了你的承诺并在上面完成了工作的人沟通。在有人向已发布的分支推送REBASE或重置后,如何恢复/重新同步?


    要修改前一个提交,请进行所需的更改并准备这些更改,然后运行

    1
    git commit --amend

    这将在文本编辑器中打开一个代表新提交消息的文件。它开始时填充了旧提交消息中的文本。根据需要更改提交消息,然后保存文件并退出编辑器以完成。

    要修改以前的提交并保留相同的日志消息,请运行

    1
    git commit --amend -C HEAD

    要通过完全删除前一个提交来修复它,请运行

    1
    git reset --hard HEAD^

    如果要编辑多个提交消息,请运行

    1
    git rebase -i HEAD~commit_count

    (用要编辑的提交数替换提交计数。)此命令启动编辑器。将第一次提交(要更改的提交)标记为"编辑"而不是"选择",然后保存并退出编辑器。进行您想要提交的更改,然后运行

    1
    2
    git commit --amend
    git rebase --continue

    注:您也可以从git commit --amend打开的编辑器中"进行您想要的更改"。


    如前所述,git commit --amend是覆盖最后一个提交的方法。一个注意事项:如果您还想覆盖这些文件,命令将是

    1
    git commit -a --amend -m"My new commit message"


    您也可以使用git-filter-branch

    1
    git filter-branch -f --msg-filter"sed 's/errror/error/'" $flawed_commit..HEAD

    这不像一个微不足道的git commit --amend那么简单,但是如果在错误的提交消息之后已经有了一些合并,那么它特别有用。

    注意,这将尝试重写HEAD和有缺陷的commit之间的每个commit,因此您应该非常明智地选择msg-filter命令;-)


    我喜欢这样。

    1
    git commit --amend -c <commit ID>

    否则,将使用新的提交ID进行新的提交。


    如果您使用的是git-gui工具,那么有一个名为amend last commit的按钮。单击那个按钮,它将显示您最后一次提交的文件和消息。只需编辑该消息,您就可以用新的提交消息提交它。

    或者从控制台/终端使用此命令:

    1
    git commit -a --amend -m"My new commit message"

    您可以使用git重新平衡。例如,如果要修改back以提交bbc643cd,请运行

    1
    $ git rebase bbc643cd^ --interactive

    在默认编辑器中,将要修改其提交的行中的"pick"修改为"edit"。做出你的改变,然后用

    1
    $ git add <filepattern>

    现在你可以使用

    1
    $ git commit --amend

    修改提交,然后

    1
    $ git rebase --continue

    返回上一个头提交。


  • 如果只想修改最后一条提交消息,请执行以下操作:

    1
    git commit --amend

    这将使您进入文本退出器,并允许您更改最后一条提交消息。

  • 如果您要更改最后3条提交消息,或到该点为止的任何提交消息,请将HEAD~3提供给git rebase -i命令:

    1
    git rebase -i HEAD~3

  • 如果必须在多个分支上更改旧的提交消息(即,多个分支中存在带有错误消息的提交),则可能需要使用:

    1
    2
    git filter-branch -f --msg-filter \
    'sed"s//<new message>/g"' -- --all

    Git将创建一个临时目录,用于重写和备份refs/original/中的旧引用。

    • -f将强制执行操作。如果临时目录已经存在,或者已经在refs/original下存储了引用,则需要这样做。如果不是这样,您可以删除此标志。

    • --将过滤分支选项与修订选项分开。

    • --all将确保重写所有分支和标记。

    由于备份了旧的引用,因此可以在执行命令之前轻松返回状态。

    比如说,你想找回你的主人,然后在old_master分局进入它:

    1
    git checkout -b old_master refs/original/refs/heads/master


    使用

    1
    git commit --amend

    要详细了解它,一个优秀的职位是4。正在重写Git历史。它还讨论了何时不使用git commit --amend


    修正

    你有几个选择。你可以做到

    1
    git commit --amend

    只要这是你最后的承诺。

    交互式钢筋网

    否则,如果这不是您最后一次提交,您可以执行交互式重新平衡,

    1
    git rebase -i [branched_from] [hash before commit]

    然后,在交互式钢筋库中,您只需向该提交添加编辑。当它出现时,执行git commit --amend并修改提交消息。如果您想在提交点之前回滚,也可以使用git reflog,只需删除该提交。然后你再做一次git commit


    如果您使用的是Git图形用户界面,那么您可以修改最后一次未被推送的提交:

    1
    Commit/Amend Last Commit


    如果这是你最后的承诺,只需修改承诺:

    1
    git commit --amend -o -m"New commit message"

    (使用-o(--only标志确保只更改提交消息)

    如果这是一个隐藏的提交,请使用令人敬畏的交互式钢筋:

    1
    git rebase -i @~9   # Show the last 9 commits in a text editor

    找到所需的提交,将pick更改为r(reword),然后保存并关闭文件。完成!

    微型VIM教程(或者,如何只使用8次击键3jODOCX1〔6〕rXKBDOCX1〔8〕)进行重新设定):

    • 有时间的话运行vimtutor
    • hdocx1〔11〕docx1〔12〕docx1〔13〕对应于运动键
    • 所有命令都可以加上前缀"range",例如xykb3j向下移动3行
    • xykbi进入插入模式-您键入的文本将出现在文件中
    • escctrlxykbeddocx1〔16〕退出插入模式,返回"正常"模式
    • xykbu撤销
    • ctrlxykbeddocx1〔3〕重做
    • xykbdd、xykbdw、xykbdl分别删除一行、一个字或一个字母。
    • xykbcc、xykbcw、xykbcl分别更改行、字或字母(同xykbddxykbeddocx1〔15〕)
    • xykbyy、xykbyw、xykbyl分别复制("扬克")一行、一个字或一封信。
    • xykbp或xykbp分别粘贴在当前位置之后或之前
    • DEOCX1〔32〕Enter,用于保存(写入)文件
    • DEOCX1〔33〕Enter不保存退出
    • :wqEnterZZ保存退出

    如果你经常编辑文本,然后切换到dvorak键盘布局,学习触摸类型,学习vim。值得付出努力吗?对。

    提示?:不要害怕尝试重写历史记录的"危险"命令*-git默认情况下90天内不会删除您的提交;您可以在reflog中找到它们:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ git reset @~3   # go back 3 commits
    $ git reflog
    c4f708b HEAD@{0}: reset: moving to @~3
    2c52489 HEAD@{1}: commit: more changes
    4a5246d HEAD@{2}: commit: make important changes
    e8571e4 HEAD@{3}: commit: make some changes
    ... earlier commits ...
    $ git reset 2c52489
    ... and you're back where you started

    *但是,要注意像--hard--force这样的选项——它们可以丢弃数据。*另外,不要在你合作的任何分支上重写历史。


    我尽可能多地使用Git GUI,这使您可以选择修改最后一次提交:

    Tick that box

    此外,git rebase -i origin/master是一个很好的咒语,它将永远向您呈现您在主服务器上所做的承诺,并给您修改、删除、重新排序或挤压的选项。不需要先抓住这个散列值。


    哇,有很多方法可以做到。

    另一种方法是删除最后一次提交,但是保留它的更改,这样就不会丢失您的工作。然后,您可以使用已更正的消息执行另一个提交。这看起来像这样:

    1
    2
    git reset --soft HEAD~1
    git commit -m 'New and corrected commit message'

    如果忘记添加文件或进行更改,我总是这样做。

    记住指定--soft而不是--hard,否则您将完全失去该承诺。


    对于任何希望使用Windows/Mac图形用户界面来帮助编辑旧消息(即,不仅仅是最新消息)的人,我建议使用sourcetree。下面是要遵循的步骤。

    SourceTree interactive rebase

    对于尚未推送到远程的提交:

  • 确保您已提交或存储了所有当前更改(即"文件状态"选项卡中没有列出任何文件),否则将无法工作。
  • 在"Log/History"选项卡中,右键单击要编辑的提交下面的图中相邻一行的条目,然后选择"Rebase children ofinteractively…"
  • 选择要更改的提交消息的整行(即单击"消息"列)。
  • 点击"编辑信息"按钮。
  • 根据需要在弹出的对话框中编辑消息,然后单击"确定"。
  • 如果还有其他提交消息要更改,请重复步骤3-4。
  • 单击确定:重新定位将开始。如果一切正常,输出将结束"成功完成"。
  • …或…对于已推送的提交:

    请遵循此答案中的步骤,与上面类似,但需要从命令行运行进一步的命令以强制推送分支-全部读取并应用必要的警告!


    如果只想编辑最新提交,请使用:

    1
    git commit --amend

    1
    git commit --amend -m 'one line message'

    但是,如果要在一行中编辑多个提交,则应改为使用重新平衡:

    1
    git rebase -i <hash of one commit before the wrong commit>

    git rebase editing

    在上述文件中,写入编辑/e或其他选项之一,然后单击保存并退出。

    现在你就要犯错误了。对文件进行更改,它们将自动为您进行转移。类型

    1
    git commit --amend

    保存并退出,然后键入

    1
    git rebase --continue

    移动到下一个选择,直到完成所有选择。

    注意,在特定的提交之后,这些事情会改变您的所有sha散列。


    如果您只想更改最后一条消息,则应使用--only标志或其快捷方式-ocommit --amend

    1
    git commit --amend -o -m"New commit message"

    这确保了你不会意外地用一些阶段性的东西来增强你的承诺。当然,最好有一个适当的$EDITOR配置。然后您可以将-m选项保留在外,Git将用旧的提交消息预先填充提交消息。这样就可以很容易地进行编辑。


    在一行中用新的提交消息更新上一个错误的提交消息:

    1
    git commit --amend -m"your new commit message"

    或者,尝试如下Git重置:

    1
    2
    3
    4
    5
    6
    7
    # You can reset your head to n number of commit
    # NOT a good idea for changing last commit message
    # but you can get an idea to split commit into multiple commits
    git reset --soft HEAD^

    # it will reset you last commit. Now, you
    # can re-commit it with new commit message.

    使用重置将提交拆分为较小的提交

    git reset也可以帮助您将一个承诺分解为多个承诺:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    # reset your head. I am resetting to last commits:
    git reset --soft HEAD^
    # (you can reset multiple commit by doing HEAD~2(no. of commits)

    # Now, reset your head for splitting it to multiple commits
    git reset HEAD

    # add and commit your files seperately to make multiple commits: e.g
    git add app/
    git commit -m"add all files in app directory"

    git add config/
    git commit -m"add all files in config directory"

    在这里,您成功地将上一次提交分为两次提交。


    在这个问题上,有很多答案,但没有一个能非常详细地解释如何使用VIM更改较旧的提交消息。我一直在尝试自己做这件事,所以在这里我将详细地写下我是如何做这件事的,尤其是对于那些没有经验的人。

    我想更改我已经提交给服务器的五个最新提交。这是非常"危险"的,因为如果已经有人从中退出,您可以通过更改提交消息来把事情搞砸。然而,当你在自己的小树枝上工作时,确保没有人拉它,你可以这样改变它:

    假设您要更改五个最新提交,然后在终端中键入:

    git rebase -i HEAD~5*其中5是要更改的提交消息数。(因此,如果要将第10次提交更改为最后一次提交,请键入10)

    这个命令将使您进入vim,您可以在那里"编辑"提交历史记录。您将在顶部看到最后5个提交,如下所示:

    pick commit message

    你要写的不是pick,而是reword。您可以在vim中通过在i中键入来实现这一点,这将使您进入插入模式。(您会看到您正处于插入模式,在底部的单词insert)对于您想要在reword而不是pick中更改类型的提交。

    然后,您需要保存并退出此屏幕,您可以通过按Esc按钮进入"命令模式"来完成此操作。(您可以检查是否处于命令模式,如果底部插入的单词消失了),则可以通过键入:键入命令,要保存和退出的命令是wq。所以如果你输入:wq,你就不是正确的路径。

    然后Vim将检查您想要改写的每个提交消息,这里您可以实际更改提交消息。您将进入插入模式,更改提交消息,进入命令模式,保存并退出。这样做5次,你就失去了活力!

    然后,如果您已经推错了承诺,那么您需要git push --force来覆盖它们。记住,git push --force是一个非常危险的操作,所以请确保自从您推错了提交之后,没有人从服务器上拉出来!

    现在您已经更改了提交消息!

    (正如你所看到的,我在维姆身上没有那么有经验,所以如果我用错误的"行话"来解释发生了什么,请随时纠正我!)


    您可以使用重新加工的git-rebase

    它的设计目的是以与commit --amend相同的方式编辑任何提交(不仅仅是最后一次提交)。

    1
    $ git rebase-reword <commit-or-refname>

    它以修改提交的Rebase Interactive操作命名:"reworked"。见本帖与人章节互动模式-

    实例:

    1
    2
    $ git rebase-reword b68f560
    $ git rebase-reword HEAD^


    我已经为recommit (amend)添加了recirecm的别名,现在我可以用git recmgit recm -m来做了。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    $ vim ~/.gitconfig

    [alias]

        ......
        cm = commit
        reci = commit --amend
        recm = commit --amend
        ......


    我意识到我犯了一个错误。为了撤消,我执行了以下操作:

    1
    2
    git commit --amend -m"T-1000, advanced prototype"
    git push --force

    警告:强制执行更改将用本地分支覆盖远程分支。确保你不会重写任何你想保留的东西。如果其他人与您共享分支,那么也要谨慎地强制执行修改(重写)提交,因为如果他们拥有您刚刚重写的提交的旧副本,那么他们需要重写自己的历史。


    我喜欢使用以下方法:

  • git status
  • git add --all
  • git commit -am"message goes here about the change"
  • git pull
  • git push

  • 如果您没有将代码推送到远程分支(github/bitback),您可以在命令行上更改commit消息,如下所示。

    1
     git commit --amend -m"Your new message"

    如果您在一个特定的分支上工作,请执行以下操作:

    1
    git commit --amend -m"BRANCH-NAME: new message"

    如果您已经用错误的消息推送了代码,那么在更改消息时需要小心。也就是说,在您更改提交消息并再次尝试推送之后,最终会出现问题。要使其平滑,请执行以下步骤。

    在做这件事之前,请把我的全部答案都读一遍。

    1
    2
    3
    git commit --amend -m"BRANCH-NAME : your new message"

    git push -f origin BRANCH-NAME                # Not a best practice. Read below why?

    重要提示:当您直接使用force push时,您可能会遇到其他开发人员正在处理同一分支的代码问题。因此,为了避免这些冲突,您需要在强制执行之前从分支中提取代码:

    1
    2
    3
     git commit --amend -m"BRANCH-NAME : your new message"
     git pull origin BRANCH-NAME
     git push -f origin BRANCH-NAME

    这是更改提交消息(如果已经推送)时的最佳实践。