ChatGPT解决这个技术问题 Extra ChatGPT

如何修改特定的提交?

我有以下提交历史:

头头~头~2头~3头

git commit --amend 修改当前的 HEAD 提交。但是如何修改 HEAD~3

在此处查看替代答案:stackoverflow.com/a/18150592/520567 您接受的答案确实是您问题的准确答案,但如果您在决定使用编辑之前已准备好新提交,那么此答案会更直接。它还可以处理您想要与旧提交合并/压缩的多个提交。
您也可以查看 Splitting a commit in Git Tools - Rewriting History 了解更多信息。

M
Mateen Ulhaq

使用 git rebase。例如,要修改提交 bbc643cd,请运行:

$ git rebase --interactive 'bbc643cd^'

请注意命令末尾的插入符号 ^,因为您实际上需要变基回 the commit before the one you wish to modify

在默认编辑器中,将提及 bbc643cd 的行中的 pick 修改为 edit

保存文件并退出。 git 将解释并自动执行文件中的命令。您会发现自己处于刚刚创建提交 bbc643cd 的先前情况。

此时,bbc643cd 是您的最后一次提交,您可以easily amend it。进行更改,然后使用以下命令提交:

$ git commit --all --amend --no-edit

之后,使用以下命令返回到之前的 HEAD 提交:

$ git rebase --continue

警告:请注意,这将更改该提交以及所有子项的 SHA-1——换句话说,这将重写从那时起的历史记录。 You can break repos doing this 如果您使用命令 git push --force 推送。


此流程中的另一个有趣选项是,一旦您移至要修改的提交,而不是修改文件并在顶部的提交(您正在编辑的那个)上进行修改,您可能希望将该提交拆分为两个不同的提交(甚至更多)。在这种情况下,回到提交进行编辑,然后运行“git reset HEAD^”。这会将修改后的提交文件放入阶段。现在根据需要选择并提交任何文件。这个流程在“git-rebase”手册页中有很好的解释。请参阅“拆分提交”部分。 bit.ly/d50w1M
在 Git 1.6.6 和更高版本中,您可以在 git rebase -i 中使用 reword 操作而不是 edit(它会自动打开编辑器并继续执行其余的变基步骤;这避免了使用 git commit --ammend 和 { 5} 当您只需要更改提交消息而不是内容时)。
值得注意的是,如果您有待处理的更改,您可能需要在 git rebase 之前运行 git stash 并在之后运行 git stash pop
是否有一个快捷命令来编辑交互式 rebase 中的特定提交,而无需打开编辑器、找到提交、将其标记为编辑,然后返回命令行?
请注意,对于较新的 git,最好遵循提示说明而不是在这里盲目使用 git commit --all --amend --no-edit。在 git rebase -i ... 之后我所要做的就是正常地 git commit --amend 然后 git rebase --continue
C
Community

使用很棒的交互式变基:

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

找到您想要的提交,将 pick 更改为 e (edit),然后保存并关闭文件。 Git 将回退到该提交,允许您:

使用 git commit --amend 进行更改,或

使用 git reset @~ 放弃最后一次提交,但不放弃对文件的更改(即带您到您编辑文件但尚未提交时所处的位置)。

后者对于做更复杂的事情很有用,比如拆分成多个提交。

然后,运行 git rebase --continue,Git 将在您修改的提交之上重放后续更改。您可能会被要求修复一些合并冲突。

注意:@HEAD 的简写,~ 是指定提交之前的提交。

在 Git 文档中阅读有关 rewriting history 的更多信息。

不要害怕变基

ProTip™:不要害怕尝试重写历史记录的“危险”命令*——Git 默认在 90 天内不会删除您的提交;您可以在 reflog 中找到它们:

$ 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 rebase -i 默认会打开 Vim。 Vim 不像大多数现代文本编辑器那样工作,所以看看 how to rebase using Vim。如果您希望使用其他编辑器,请使用 git config --global core.editor your-favorite-text-editor 进行更改。


这应该用于已经推送到远程分支的提交吗?
git reset @~ 正是我在使用 git rebase ... 选择提交后想要做的。你是我的英雄)
对于想要编辑第一个提交的人:git rebase -i --root
这真的很棒——谢谢。在使用 git reset @~ 进行一些更新(主要是 git checkout file-i-didn't-mean-to-change)之后,是否有一种简单的方法可以将该提交与原始消息一起放回?我从 git status 的简介输出中复制了原始消息,然后运行 git rebase --continue,但我想知道是否有更简单的方法?也许如果没有更简单的方法,您也可以在回答中简要提及这一点?
啊!我想我可以使用:git reset @~ -- file-i-didn't-mean-to-change 后跟 git commit --amend --no-edit
t
thrau

当我需要更深入地修复历史中的先前提交时,我经常使用与 --autosquash 交互的 rebase。它从本质上加快了 ZelluX 的回答所说明的过程,并且当您需要编辑多个提交时特别方便。

从文档中:

--autosquash 当commit log message以“squash!...”(或“fixup!...”)开头,并且有一个标题以相同...开头的commit时,自动修改rebase -i的todo列表,使该commit在要修改的提交之后立即标记为挤压

假设您的历史记录如下所示:

$ git log --graph --oneline
* b42d293 Commit3
* e8adec4 Commit2
* faaf19f Commit1

并且您有要修改到 Commit2 的更改,然后使用

$ git commit -m "fixup! Commit2"

或者,您可以使用 commit-sha 代替提交消息,因此 "fixup! e8adec4 甚至只是提交消息的前缀。

然后在之前的提交上启动交互式变基

$ git rebase e8adec4^ -i --autosquash

您的编辑器将打开已正确排序的提交

pick e8adec4 Commit2
fixup 54e1a99 fixup! Commit2
pick b42d293 Commit3

您需要做的就是保存并退出


您也可以使用 git commit --fixup=@~ 代替 git commit -m "fixup! Commit2"。当您的提交消息较长并且输入整个内容会很痛苦时,这尤其有用。
我为我的 .gitconfig 写了一个别名来简化这个 fixup = "!fn() { git commit --fixup ${1} && GIT_EDITOR=true git rebase --autosquash -i ${1}^; }; fn -> git fixup <commitId> 修改给定提交的所有分阶段更改
谢谢@thrau!但它缺少结束 "
Thraus 别名似乎不适用于短提交哈希。这个有效:fixup = "!fn() { git commit -m \"fixup! ${1}\" && GIT_EDITOR=true git rebase --autosquash -i ${1}^; }; fn"
现在适用于 HEADHEAD^HEAD~7 等:fixup = "!fn() { _FIXUP_COMMIT=`git rev-parse $HEAD` && git commit -m \"fixup! ${_FIXUP_COMMIT}\" && GIT_EDITOR=true git rebase --autosquash -i ${_FIXUP_COMMIT}^; }; fn"
b
betoharres

跑:

$ git rebase --interactive commit_hash^

每个 ^ 表示您想要编辑多少次提交,如果它只有一个(您指定的提交哈希),那么您只需添加一个 ^

使用 Vim 将单词 pick 更改为 reword 以表示要更改、保存和退出 (:wq) 的提交。然后 git 将提示您标记为 reword 的每个提交,以便您可以更改提交消息。

您必须保存并退出(:wq)每条提交消息才能转到下一个提交消息

如果您想退出而不应用更改,请按 :q!

编辑:要在 vim 中导航,您使用 j 向上,k 向下,h 向左,l 向右(所有这些都在 { 6} 模式,按 ESC 进入 NORMAL 模式)。要编辑文本,请按 i 进入 INSERT 模式,在此插入文本。按 ESC 返回 NORMAL 模式 :)

更新:这是来自 github 列表的一个很好的链接 How to undo (almost) anything with git


非常适合我。值得一提 git push --force
git push --force 所做的是用您的本地提交覆盖远程提交。这不是本主题的情况:)
@BetuUuUu 当然,如果您的提交被推送到远程并且您在本地修改了提交消息,您会想要强制推送到远程,不是吗?
@SudipBhandari 这就是我的感觉。我没有强制,现在我有一个额外的分支,将所有提交镜像回我更改了消息的那个,这非常丑陋。
@greenhouse 如果您修改并强制推送,那么其他团队成员很可能会遇到合并冲突。因此,您通常应该对此非常谨慎。但是,如果您修改了其他人尚未获取的内容,那应该没问题(不会注意到它)。所以我会考虑 --force 作为最后的手段,并总是与其他成员咨询回购的状态。
s
sikander

基于 Documentation

修改旧的或多个提交消息的消息

git rebase -i HEAD~3 

上面显示了当前分支上最后 3 次提交的列表,如果您想要更多,请将 3 更改为其他内容。该列表将类似于以下内容:

pick e499d89 Delete CNAME
pick 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

在您要更改的每条提交消息之前将 pick 替换为 reword 。假设您更改了列表中的第二个提交,您的文件将如下所示:

pick e499d89 Delete CNAME
reword 0c39034 Better README
pick f7fde4a Change the commit message but push the same commit.

保存并关闭提交列表文件,这将弹出一个新的编辑器供您更改提交消息,更改提交消息并保存。

最后,强制推送修改后的提交。

git push --force

我收到以下错误:错误:编辑器“vi”出现问题。请使用 -m 或 -F 选项提供消息。
“reword”选项是一个很好的工具,但是“git push --force”是危险的。如果我们想要更改提交消息的提交尚未提交,那么 --force 不是必需的。 --force 选项会重写远程代表的历史记录,并且需要更多权限。如果要修改仅位于计算机上的提交,则不需要 --force;如果提交已经被推送,除非绝对必要,否则您不应更改它。
D
Dethariel

完全非交互式命令(1)

我只是想我会分享一个我为此使用的别名。它基于非交互式交互式变基。要将其添加到您的 git,请运行以下命令(解释如下):

git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^"; }; f'

或者,一个也可以处理未暂存文件的版本(通过存储然后取消存储它们):

git config --global alias.amend-to '!f() { SHA=`git rev-parse "$1"`; git stash -k && git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" && git stash pop; }; f'

这个命令的最大优点是它没有 vim。

(1)假设在变基期间没有冲突,当然

用法

git amend-to <REV> # e.g.
git amend-to HEAD~1
git amend-to aaaa1111

恕我直言,名称 amend-to 似乎很合适。将流程与 --amend 进行比较:

git add . && git commit --amend --no-edit
# vs
git add . && git amend-to <REV>

解释

git config --global alias. '!' - 创建一个名为 的全局 git 别名,它将执行非 git 命令

f() { <身体> }; f - “匿名” bash 函数。

SHA=`git rev-parse "$1"`; - 将参数转换为 git 修订版,并将结果分配给变量 SHA

git commit --fixup "$SHA" - SHA 的修复提交。请参阅 git-commit 文档

GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" git rebase --interactive "$SHA^" 部分已被其他答案覆盖。 --autosquash 是与 git commit --fixup 一起使用的,有关更多信息,请参阅 git-rebase 文档 GIT_SEQUENCE_EDITOR=true 是使整个事物非交互的原因。我从这篇博文中学到了这个技巧。

git rebase --interactive "$SHA^" 部分已被其他答案覆盖。

--autosquash 与 git commit --fixup 一起使用,有关更多信息,请参阅 git-rebase 文档

GIT_SEQUENCE_EDITOR=true 使整个事情变得非交互式。我从这篇博文中学到了这个技巧。


还可以让 amend-to 处理未暂存的文件:git config --global alias.amend-to '!f() { SHA=git rev-parse "$1"; git stash -k && git commit --fixup "$SHA" && GIT_SEQUENCE_EDITOR=true git rebase --interactive --autosquash "$SHA^" && git stash pop; }; f'
这种方法的一个问题是它可能会应用不相关的修复。
问题的重点不是更改提交消息吗?因为这个答案没有解决这个问题,或者至少没有直接解决。
@wytten 问题不是关于更改提交消息,而是关于修改不是 HEAD 的提交。所以你的问题的答案是“不,这不是问题的重点”
我很困惑,那么我们如何更改提交消息?
F
FeepingCreature

如果由于某种原因您不喜欢交互式编辑器,您可以使用 git rebase --onto

假设您要修改 Commit1。首先,从 before Commit1 分支:

git checkout -b amending [commit before Commit1]

其次,用 cherry-pick 抓取 Commit1

git cherry-pick Commit1

现在,修改您的更改,创建 Commit1'

git add ...
git commit --amend -m "new message for Commit1"

最后,在隐藏任何其他更改之后,将其余的提交移植到 master 到您的新提交之上:

git rebase --onto amending Commit1 master

阅读:“rebase,到分支 amendingCommit1(不包括)和 master(包括)之间的所有提交”。即 Commit2 和 Commit3,将旧的 Commit1 完全剔除。你可以挑选它们,但这种方式更容易。

记得清理你的树枝!

git branch -d amending

您可以使用 git checkout -b amending Commit1~1 获取先前的提交
前两个步骤是否等同于 git checkout -b amending Commit1
对于害怕交互式 rebase 的人来说,这是一个很好的答案。我唯一的抱怨是没有必要从较早的提交开始并挑选你想要修改的实际提交。您可以只分支给定的提交并如图所示修改它,跳过cherrypick步骤。事实上,cherrypicking 只会将你的分支快进一个提交,就像你直接从这个提交分支一样。
C
Ciro Santilli Путлер Капут 六四事

git stash + rebase 自动化

因为当我需要为 Gerrit 审查多次修改旧提交时,我一直在做:

git-amend-old() (
  # Stash, apply to past commit, and rebase the current branch on to of the result.
  current_branch="$(git rev-parse --abbrev-ref HEAD)"
  apply_to="$1"
  git stash
  git checkout "$apply_to"
  git stash apply
  git add -u
  git commit --amend --no-edit
  new_sha="$(git log --format="%H" -n 1)"
  git checkout "$current_branch"
  git rebase --onto "$new_sha" "$apply_to"
)

GitHub upstream

用法:

修改源文件,如果已经在 repo 中就不需要 git add

git-amend-old $old_sha

我喜欢 --autosquash,因为它不会压缩其他不相关的修复。


非常好的解决方法,这应该是 git amend 的默认选项,以使用当前存储将更改应用于特定提交,非常聪明!
D
DINA TAKLIT

最好的选择是使用“交互式变基命令”。

git rebase 命令非常强大。它允许您编辑提交消息、合并提交、重新排序......等等。每次您重新提交提交时,都会为每个提交创建一个新的 SHA,无论内容是否会更改!使用此命令时应小心,因为它可能会产生重大影响,尤其是在您与其他开发人员合作时。他们可能会在您重新设置一些基础时开始处理您的提交。在您强制推送提交后,它们将不同步,您稍后可能会在混乱的情况下发现。所以要小心!建议在变基之前创建一个备份分支,这样每当您发现事情失控时,您都可以返回到以前的状态。

现在如何使用这个命令?

git rebase -i <base> 

-i 代表“交互式”。请注意,您可以在非交互模式下执行变基。前任:

#interactivly rebase the n commits from the current position, n is a given number(2,3 ...etc)
git rebase -i HEAD~n 

HEAD 表示您当前的位置(也可以是分支名称或提交 SHA)。 ~n 表示“n beforeé”,因此 HEAD~n 将是您当前所在的提交之前的“n”个提交列表。

git rebase 有不同的命令,例如:

p 或选择保持原样提交。

r 或 reword:保留提交的内容但更改提交消息。

s 或 squash:将此提交的更改合并到上一个提交中(列表中它上面的提交)。

... 等等 注意:最好让 Git 与您的代码编辑器一起工作,以使事情变得更简单。例如,如果您使用可视代码,您可以像这样添加 git config --global core.editor "code --wait"。或者您可以在 Google 中搜索如何将您喜欢的代码编辑器与 GIT 相关联。

git rebase 示例

我想更改我所做的最后 2 次提交,所以我处理如下:

显示当前提交:#This 在一行上显示所有提交 $git log --oneline 4f3d0c8 (HEAD -> 文档) docs: Add project description and included files" 4d95e08 docs: Add created date and project title" eaf7978 (origin /master , origin/HEAD, master) 初始提交 46a5819 创建 README.md 现在我使用 git rebase 更改最后的 2 个提交消息: $git rebase -i HEAD~2 它打开代码编辑器并显示:pick 4d95e08 文档:添加创建日期和项目标题 pick 4f3d0c8 文档:添加项目描述和包含的文件 # Rebase eaf7978..4f3d0c8 到 eaf7978(2 个命令)# # 命令:# p, pick = use commit # r, reword =使用提交,但编辑提交消息......因为我想更改这 2 个提交的提交消息。所以我会输入 r 或 reword 来代替 pick。然后保存文件并关闭选项卡。请注意,rebase 是在多步骤过程中执行的,因此下一步是更新消息。另请注意,提交按时间倒序显示,因此最后一次提交显示在该提交中,第一次提交显示在第一行,依此类推。更新消息:更新第一条消息:文档:将创建日期和项目标题添加到文档“README.md”# 请输入您的更改的提交消息。以“#”开头的 # 行将被忽略,并且一条空消息中止提交。 ...保存并关闭编辑第二条消息文档:将项目描述和包含的文件添加到文档“README.md”#请输入您的更改的提交消息。以“#”开头的 # 行将被忽略,并且一条空消息中止提交。 ... 保存并关闭。在 rebase 结束时你会收到这样的消息:Successfully rebase and updated refs/heads/documentation 这意味着你成功了。您可以显示更改: 5dff827 (HEAD -> 文档) 文档:将项目描述和包含的文件添加到文档“README.md” 4585c68 文档:将创建日期和项目标题添加到文档“README.md” eaf7978 (origin/ master, origin/HEAD, master) 初始提交 46a5819 创建 README.md 我希望这可以帮助新用户:)。


T
Tom Hale

自动交互式 rebase 编辑,然后提交恢复准备好进行重做

我发现自己经常修复过去的提交,以至于我为它编写了一个脚本。

这是工作流程:

git commit-edit 这会将你放到你想要编辑的提交处。修复并按您希望的方式暂存提交。 (您可能希望使用 git stash save 来保留您未提交的任何文件)使用 --amend 重做提交,例如: git commit --amend 完成 rebase: git rebase --continue

为使上述操作生效,请将以下脚本放入 $PATH 中某处名为 git-commit-edit 的可执行文件中:

#!/bin/bash

set -euo pipefail

script_name=${0##*/}

warn () { printf '%s: %s\n' "$script_name" "$*" >&2; }
die () { warn "$@"; exit 1; }

[[ $# -ge 2 ]] && die "Expected single commit to edit. Defaults to HEAD~"

# Default to editing the parent of the most recent commit
# The most recent commit can be edited with `git commit --amend`
commit=$(git rev-parse --short "${1:-HEAD~}")
message=$(git log -1 --format='%h %s' "$commit")

if [[ $OSTYPE =~ ^darwin ]]; then
  sed_inplace=(sed -Ei "")
else
  sed_inplace=(sed -Ei)
fi

export GIT_SEQUENCE_EDITOR="${sed_inplace[*]} "' "s/^pick ('"$commit"' .*)/edit \\1/"'
git rebase --quiet --interactive --autostash --autosquash "$commit"~
git reset --quiet @~ "$(git rev-parse --show-toplevel)"  # Reset the cache of the toplevel directory to the previous commit
git commit --quiet --amend --no-edit --allow-empty  #  Commit an empty commit so that that cache diffs are un-reversed

echo
echo "Editing commit: $message" >&2
echo

O
Olga

采用了这种方法(它可能与使用交互式 rebase 完全相同),但对我来说这很简单。

注意:我提出这种方法是为了说明您可以做什么,而不是日常替代方案。因为它有很多步骤(可能还有一些警告。)

假设您要更改提交 0 并且您当前在 feature-branch

some-commit---0---1---2---(feature-branch)HEAD

签出此提交并创建一个 quick-branch。您还可以克隆您的功能分支作为恢复点(在开始之前)。

?(git checkout -b feature-branch-backup)
git checkout 0
git checkout -b quick-branch

您现在将拥有如下内容:

0(quick-branch)HEAD---1---2---(feature-branch)

阶段变化,藏匿一切。

git add ./example.txt
git stash

提交更改并结帐回 feature-branch

git commit --amend
git checkout feature-branch

您现在将拥有如下内容:

some-commit---0---1---2---(feature-branch)HEAD
           \
             ---0'(quick-branch)

feature-branch 重新设置为 quick-branch(解决沿途的任何冲突)。应用存储并删除 quick-branch

git rebase quick-branch
git stash pop
git branch -D quick-branch

你最终得到:

some-commit---0'---1'---2'---HEAD(feature-branch)

Git 不会在变基时复制 0 提交(尽管我不能真正说出在多大程度上)。

注意:所有提交哈希都从我们最初打算更改的提交开始更改。


P
Pelle Nilsson

要获取非交互式命令,请将包含此内容的脚本放在 PATH 中:

#!/bin/sh
#
# git-fixup
# Use staged changes to modify a specified commit
set -e
cmt=$(git rev-parse $1)
git commit --fixup="$cmt"
GIT_EDITOR=true git rebase -i --autosquash "$cmt~1"

通过暂存更改(使用 git add)使用它,然后运行 git fixup <commit-to-modify>。当然,如果发生冲突,它仍然是交互式的。


这很好用。我添加了一些额外的功能来对脏树进行零碎修复,以完善提交集。 `dirtydiff=$(git diff);如果 [ "${dirtydiff}" != "" ];然后 echo "Stashing dirty tree" >&2;混帐藏匿;菲;
M
Mohideen bin Mohammed

我解决了这个,

1)通过创建带有我想要的更改的新提交..

r8gs4r commit 0

2)我知道我需要与哪个提交合并。这是提交3。

所以,git rebase -i HEAD~4 # 4 代表最近的 4 次提交(这里的第 3 次提交在第 4 位)

3) 在交互式变基中,最近的提交将位于底部。它看起来很像,

pick q6ade6 commit 3
pick vr43de commit 2
pick ac123d commit 1
pick r8gs4r commit 0

4)在这里,如果您想与特定的合并,我们需要重新安排提交。它应该是这样的,

parent
|_child

pick q6ade6 commit 3
f r8gs4r commit 0
pick vr43de commit 2
pick ac123d commit 1

重新排列后,您需要将 p pick 替换为 ffixup 将在没有提交消息的情况下合并)或 ssquash 与提交消息合并可以更改在运行时)

然后保存你的树。

现在与现有提交合并完成。

注意:除非您自己维护,否则它不是可取的方法。如果您的团队规模很大,那么重写 git 树的方法不是可接受的方法,最终会出现您知道其他人不会发生的冲突。如果你想用更少的提交来保持你的树干净,可以试试这个,如果它的小团队,否则它不是可取的.....


如果您不想在交互式变基期间进行实时修改,这是一个很好的解决方案。
M
MD SHAYON

更改最后一次提交:

git commit --amend
// or
git commit --amend -m "an updated commit message"

不要修改公共提交 修改后的提交实际上是全新的提交,之前的提交将不再在您当前的分支上。

例如,如果您想更改最后三个提交消息,或该组中的任何提交消息,您将作为参数提供给 git rebase -i 您要编辑的最后一个提交的父级,即 HEAD~2 ^ 或 HEAD~3。记住 ~3 可能更容易,因为您正在尝试编辑最后三个提交,但请记住,您实际上是在指定四个提交之前,即您要编辑的最后一个提交的父级:

$ git rebase -i HEAD~3

know more


P
Pellet

对我来说,这是为了从回购中删除一些凭据。我尝试变基并在尝试变基时遇到了大量看似无关的冲突--继续。不要费心尝试重新设置自己的基础,在 mac 上使用名为 BFG (brew install bfg) 的工具。


r
rharvey

如果您尚未推送提交,那么您可以使用 git reset HEAD^[1,2,3,4...] 返回上一个提交

例如

git commit <file1> -m "Updated files 1 and 2"
git commit <file3> -m "Updated file 3"

糟糕,忘记将 file2 添加到第一个提交中...

git reset HEAD^1 // because I only need to go back 1 commit

git add <file2>

这会将 file2 添加到第一个提交中。


A
Aidin

好吧,这个解决方案可能听起来很傻,但在某些情况下可以拯救你。

我的一个朋友刚刚遇到不小心提交了一些非常大的文件(四个自动生成的文件,每个文件的大小在 3GB 到 5GB 之间),然后在此之上提交了一些额外的代码,然后才意识到问题是 { 1} 不再工作了!

这些文件已在 .gitignore 中列出,但在重命名容器文件夹后,它们被公开并提交!现在在此之上还有一些代码提交,但 push 一直在运行(尝试上传 GB 的数据!),最后由于 Github's file size limits 而失败。

交互式变基或任何类似的问题是他们会处理这些巨大的文件,并且需要永远做任何事情。然而,在 CLI 中花费了近一个小时后,我们不确定文件(和增量)是否实际上已从历史记录中删除,或者根本不包含在当前提交中。推动也不起作用,我的朋友真的被卡住了。

所以,我想出的解决方案是:

将当前 git 文件夹重命名为 ~/Project-old。再次从 github 克隆 git 文件夹(到 ~/Project)。结帐到同一分支。手动 cp -r 将 ~/Project-old 文件夹中的文件复制到 ~/Project.确保不需要签入的大量文件已被 mved,并正确包含在 .gitignore 中。还要确保不要用旧的 ~/Project 覆盖最近克隆的 ~/Project 中的 .git 文件夹。那就是有问题的历史记录所在的地方!现在查看更改。它应该是所有最近提交的联合,不包括有问题的文件。最后提交更改,很高兴被推送。

该解决方案的最大问题是,它处理手动复制一些文件,并且还将所有最近的提交合并为一个(显然使用新的提交哈希。) B

最大的好处是,每一步都非常清晰,它适用于大文件(以及敏感文件),并且不会在历史上留下任何痕迹!