我已经尝试了所有提供的方法,即 rebase 和cherry-pick。我在这里提供有关我尝试过的方法和所做的事情的完整信息,以帮助更好地理解事情
准备工作
为了检查哪个是最好的,我做了这些事情:
-
fork 远程 repo 以便原件完好无损并且可以轻松理解。所以,在你确定所做的事情是否正确之前,不要做任何原始回购。
-
首先获取 Git Repo 的干净副本。通常,每当我们存储或做其他事情时,这些事情也作为本地 Git 数据库存储在 Git 中。所以,那个 Git 数据库没有任何本地或临时的东西。
-
我已经计算了文件夹 .git 占用的总字节数。由于 repo 是干净的,因此这里的最小字节数是正确的。为了更深入,我记录了磁盘上占用的字节数和字节数。因为两者是不同的东西,它们是:
bytes - 7,963,769 and size on disk - 8,028,160
- 如果您使用的是 Windows 并安装了任何防病毒软件,那么您必须禁用活动/实时模式。作为服务,Git 需要快速访问 i/o 文件检查。当文件由 Git 创建时会发生什么,活动模式会锁定新的 Created 以检查病毒,并且当 Git 尝试重新访问它由于防病毒锁定而失败时会发生什么。如果失败,您必须从 1 重新开始您的流程。
方法一 - 变基
在 re-basing 方法中可以通过两种方式完成。一种是通过--onto,另一种是通过-i。
-i 方法
我使用了以下命令:
git rebase -i 162f833c^
它打开了 vim 编辑器,我看到了从 162f833c 开始的提交列表,而不是来自 master。如果结尾,则提供以下几行。
# Rebase 3260327..5d39775 onto 3260327
#
# Commands:
# p, pick = use commit
# r, reword = use commit, but edit the commit message
# e, edit = use commit, but stop for amending
# s, squash = use commit, but meld into previous commit
# f, fixup = like "squash", but discard this commit's log message
# x, exec = run command (the rest of the line) using shell
#
# If you remove a line here THAT COMMIT WILL BE LOST.
# However, if you remove everything, the rebase will be aborted.
#
我删除了一行,这样提交将丢失并保存文件并退出编辑器,当我退出时,它开始重新定位,如下所示:
Rebasing ( 1/64) ..(2/64)
Successfully rebased and updated refs/heads/master.
然后尝试检查日志以查看提交是否丢失,并且在日志中我找不到要删除的提交。表示成功完成命令。我试图检查状态为:
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 64 and 65 different commit(s) each, respectively.
由于提交被删除,但在派生它的远程需要被推送。因此,使用强制推送来覆盖之前的代码。
git push -f
之后我删除了本地 repo 并再次重新获取 repo 和它显示的大小:
bytes 6,831,765 bytes
size on disk 6,897,664 bytes
--onto方法
在浏览了许多博客和手册后,我找到了 1 个博客here,这真的让我知道如何使用它。所以我使用的命令是:
git rebase --onto 3260327 79504a5~1
输出是:
First, rewinding head to replay your work on top of it...
Applying: 77th Message
Applying: 78th Message
Applying: 79th Message
....
Last commit
然后尝试检查日志以查看提交是否丢失,并且在日志中我找不到要删除的提交。表示成功完成命令。我试图检查状态为:
# On branch master
# Your branch and 'origin/master' have diverged,
# and have 64 and 65 different commit(s) each, respectively.
所以,使用单个命令完成所有事情,然后我像之前一样强制推送检查字节等
git push -f
之后我删除了本地 repo 并再次重新获取 repo 和它显示的大小:
bytes - 6,831,389
size on disk - 6,893,568
变基 -i 与 --onto
因此,在做 rebase 方法之后。我真的同意 --onto 方法来删除中间的提交,因为它是单个命令,并且字节也比 -i 方法保存得略高。真正的好处是我们不必在 --onto 方法中做额外的事情。
方法二 - 樱桃采摘
Cherry-pick 非常好的方法,但运行了许多命令,运行命令时您必须小心谨慎。首先,我必须创建一个单独的日志文件
git log --all --decorate --oneline --graph > 1
这向我展示了 repo 的日志,因为我们需要一次又一次地查看它。从这个 repo 中确定您要删除的提交并复制 SHA 密钥最后一个正确的提交含义,从而确定我们不想更改任何内容的提交。所以,下一个命令是
git checkout 3260327 -b repair
生成的输出:
Switched to a new branch 'repair'
所以,直到最后一个 Good 提交,我们已经创建了一个新分支。所以,最后的事情好提交不会改变。我再次运行以下命令来查看所有好的提交:
git log --decorate --oneline --graph > 2
我已经删除了世界 --all 因为我只想查看分支修复的提交。正如它向我展示的那样,Good Commits 标记正确。现在,下一个命令要谨慎使用,因为它包含错误提交作为起点和最后一次提交完成的终点,它将是:
git cherry-pick 162f833..5d39775
输出:
[repair 9ed3f18] xxxxxx
x files changed, xxx insertions(+), xx deletions(-)
[repair 7f06d73] xxxxx
xx files changed, xxx insertions(+), xx deletions(-)
.....
...
此命令的作用是重新提交所有提交,离开上面提供的第一个提交,即 (162f833) 到提供的最后一个提交 (5d39775)。因此,sha 提交值将在它一一重新提交时相应地更改。现在是时候查看日志了:
git log --all --decorate --oneline --graph > 3
输出为:
* f61a9a5 (HEAD, repair) xxxxxx
* 25be3b9 xxxxx
* 49be029 xxxxx
.......
.......
| * 5d39775 (origin/master, origin/HEAD, master)
| * a4df5ee xxxxx
| * 6971cf3 xxxxxx
| .......
| .......
| * 162f833 xxxx
|/
* 3260327 xxxxx
......
* 9770059 xxxxx
因此,查看图表让我们知道它已经重新提交了除错误提交之外的所有提交。向您展示所有带有新键的旧 sha 键。如果一切正常,我们必须将修复分支设为 master 并将 master 分支删除为:
git checkout master
并输出为:
Switched to branch 'master'
首先结帐 master 分支,以便我们可以覆盖 master 分支上的更改。那么
git reset --hard 3260327
并输出为:
HEAD is now at 3260327 xxxxx
它会在良好提交之后丢弃提交,现在我们必须将修复分支与 master 合并:
git merge repair
并输出为:
Updating 3260327..40d290d
Fast-forward
现在,如果您查看日志,它不会向您显示错误的提交,并且所有事情都已完成。我像之前一样强制推动检查字节等
git push -f
之后我删除了本地 repo 并再次重新获取 repo 和它显示的大小:
bytes - 6,831,556
size on disk - 6,897,664
命令排名
变基 --onto [第一]
bytes - 6,831,389
size on disk - 6,893,568
樱桃采摘[第二]
bytes - 6,831,556
size on disk - 6,897,664
变基 -i [第三个]
bytes 6,831,765 bytes
size on disk 6,897,664 bytes
我想优先使用 git rebase --onto 命令,因为使用单个命令可以轻松完成所有操作。