Git -在提交之间删除

bogh5gae  于 2023-04-10  发布在  Git
关注(0)|答案(7)|浏览(119)

我们的团队正在用PHP做几个项目。我们错误地将一个项目的文件夹提交给了另一个项目。现在,我们想从项目中删除特定的提交。如果我们从项目中删除特定的文件夹/提交,那么我们的项目就没有问题了。
如果我们只是删除文件夹并在当前位置发出新的commit,那么文件夹会被删除,但它会保留在Git的历史记录中。所以,我们希望将它从refs,历史记录和Git的其他内容中完全删除。
我们也可以创建一个单独的分支,但是作者的提交引用会丢失。我们只想删除那个特定的提交。我们在重写历史或重新建立基础方面没有问题,但不知道如何做到这一点。
在项目中,我们已经完成了136次提交,并希望删除第76次提交。

5d39775b          //136th commit
a4df5ee9          //135th commit
6971cf35          //134th commit
.....
....
162f833c          //76th commit
32603274          //75th commit
.....
....
9770059          //1st commit
uqjltbpv

uqjltbpv1#

在master分支中,您可以交互式地变基:

git rebase -i 162f833c^

这将在违规提交之前的提交的基础上进行重定。现在只需从列表中删除违规提交,保存并退出编辑器(*nix平台中的默认值是vi)。
这将使你的分支在有问题的提交之前的提交之上重新定基,而没有它,这似乎是你试图实现的。

yhuiod9q

yhuiod9q2#

我已经尝试了所有提供的方法,即rebase和cherry-pick。我在这里提供有关尝试的方法和我所做的事情的完整信息,以帮助更好地了解事情

准备工作

为了检查我做了哪些最好的事情:

  1. Fork远程repo,这样原始的代码就不会被破坏,而且很容易理解。所以,在你确定做的事情是正确的之前,不要做任何原始的repo。
    1.首先,我们使用Git Repo的干净副本。通常,每当我们存储或做其他事情时,Git也会存储在本地Git数据库中。因此,该Git数据库没有任何本地或临时内容。
    1.我已经计算了文件夹. git占用的总字节数。由于repo是干净的,所以这里的最小字节数是正确的。为了更深入地了解,我已经记下了磁盘上占用的字节数和字节数。因为两者是不同的东西,它们是:
bytes - 7,963,769 and size on disk - 8,028,160

1.如果你使用的是Windows并且安装了任何防病毒软件,那么你必须禁用Active/真实的time模式。Git需要快速访问I/O文件检查。当Git创建文件时,会发生什么?Active模式锁定新的Created文件以检查病毒,当Git试图重新访问时,由于防病毒软件锁定而失败。如果失败,你必须从1重新启动进程。

方法一- Rebase

在re-based方法中,可以通过两种方式来实现。一种是通过--onto,另一种是使用-i。

-i方法

我使用了以下命令:

git rebase -i 162f833c^

它打开了vim编辑器,我看到了从162 f833 c开始而不是从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方法

在浏览了许多博客和手册后,我发现了一个博客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 VS --转换为

因此,在执行rebase方法之后。我真的很赞成--onto方法来删除中间的提交,因为它是单个命令,而且字节数也比-i方法略高。真正的好处是我们不必在--onto方法中做额外的事情。

方法二- Cherry-pick

Cherry-pick非常好的方法,但是要运行许多命令,在运行命令时必须小心。

git log --all --decorate --oneline --graph > 1

它向我展示了repo的日志,因为我们需要一次又一次地查看它。从这个repo中识别出你想要删除的提交,并复制SHA Key,最后一个好的提交意味着识别出我们不想改变任何事情的提交。所以,下一个命令是

git checkout 3260327 -b repair

生成的输出:

Switched to a new branch 'repair'

所以,到上次Good commit为止,我们已经创建了一个新的分支。所以,到上次Good commit为止的事情没有改变。我再次运行以下命令来查看所有的good commit:

git log --decorate --oneline --graph > 2

我已经删除了世界--所有的作为,我想查看提交的分支修复只.因为它显示了我良好的提交到正确标记.现在,下一个命令是要谨慎使用,因为它是包括坏的提交作为起点和终点最后一次提交完成,它将是:

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(-)
.....
...

这个命令的作用是重新提交所有提交,从上面提供的第一次提交(162 f833)到最后一次提交(5d39775)。因此,sha commits值将相应地改变,因为它一个接一个地重新提交。现在是时候查看日志了:

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键与新的键。如果一切都是正确的,我们必须使修复分支作为主分支,并删除主分支:

git checkout master

并输出为:

Switched to branch 'master'

首先 checkout 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

命令排序

重定基数--到[第一个]

bytes - 6,831,389
size on disk - 6,893,568

Cherry Pick [第二张]

bytes - 6,831,556
size on disk - 6,897,664

Rebase -i [第三个]

bytes 6,831,765 bytes
size on disk 6,897,664 bytes

我想优先给予git rebase --onto命令,因为它可以轻松地用单个命令完成任务。

mjqavswn

mjqavswn3#

可以使用交互式变基。
因为你想删除的提交有sha1 162f833c,那么就执行git rebase -i 162f833c^
一个文本编辑器将打开一个提交列表。只需删除与您想要删除、保存和关闭的提交相对应的行。
作为一个安全网,当我做这类事情的时候,我喜欢先在我的HEAD上放一个标签,这样如果出了问题,我就可以 checkout 这个标签并检索我的初始状态。

inb24sb2

inb24sb24#

您可以通过以下方式自动删除提交并重写历史(其中${ref_to_delete}是您要删除的提交,并假设master是它所在的分支):

git rebase --onto ${ref_to_delete}~ ${ref_to_delete} master

如果使用远程仓库,则必须使用-f执行push

git push -f
fkvaft9z

fkvaft9z5#

你也可以使用git cherry-pick来实现:

$ g  # g is my alias for git log --all --decorate --oneline --graph --color
* 618f8e5 [2013-12-14 15:13] (HEAD, master) me: good 6
* e27d6d7 [2013-12-14 15:13] me: good 5
* 533f6c3 [2013-12-14 15:13] me: good 4
* 877585f [2013-12-14 15:13] me: bad
* 00c06f3 [2013-12-14 15:12] me: good 3
* e9f80a4 [2013-12-14 15:12] me: good 2
* 3122ba7 [2013-12-14 15:12] me: good 1
* 98da603 [2013-12-14 15:12] me: first
$ git checkout 00c06f3 -b repair
Switched to a new branch 'repair'
$ git cherry-pick 877585f..618f8e5
[repair b340e21] good 4
 1 file changed, 1 insertion(+)
[repair 1d2e0d0] good 5
 1 file changed, 1 insertion(+)
[repair 1ed1d19] good 6
 1 file changed, 1 insertion(+)
$ g
* 1ed1d19 [2013-12-14 15:13] (HEAD, repair) me: good 6
* 1d2e0d0 [2013-12-14 15:13] me: good 5
* b340e21 [2013-12-14 15:13] me: good 4
| * 618f8e5 [2013-12-14 15:13] (master) me: good 6
| * e27d6d7 [2013-12-14 15:13] me: good 5
| * 533f6c3 [2013-12-14 15:13] me: good 4
| * 877585f [2013-12-14 15:13] me: bad
|/  
* 00c06f3 [2013-12-14 15:12] me: good 3
* e9f80a4 [2013-12-14 15:12] me: good 2
* 3122ba7 [2013-12-14 15:12] me: good 1
* 98da603 [2013-12-14 15:12] me: first
$ git checkout master
Switched to branch 'master'
$ git reset --hard repair
HEAD is now at 1ed1d19 good 6
$ git branch -d repair
Deleted branch repair (was 1ed1d19).
$ g
* 1ed1d19 [2013-12-14 15:13] (HEAD, master) me: good 6
* 1d2e0d0 [2013-12-14 15:13] me: good 5
* b340e21 [2013-12-14 15:13] me: good 4
* 00c06f3 [2013-12-14 15:12] me: good 3
* e9f80a4 [2013-12-14 15:12] me: good 2
* 3122ba7 [2013-12-14 15:12] me: good 1
* 98da603 [2013-12-14 15:12] me: first
$ # Done :)

git rebase可能更好,所以至少我展示了在git中通常有多种方法。毕竟,rebase是如此强大,以至于“git中所有有意义的操作都可以用rebase命令来表达”(Linus Torvalds)。

b91juud3

b91juud36#

git rebase -i 32603274..这将显示一个巨大的提交列表。
pick 162f833c .. pick ...
将第一次提交更改为d 162 f833 c..
保存它
这将仅丢弃第76次提交

knpiaxh1

knpiaxh17#

有些仓库会被管理员保护,以防止更改历史记录,就像我的例子一样,为此我不得不使用git revert
git revert 162f833c
这也更安全,因为如果你想把它带回来,你仍然有错误的提交。如果你想把它带回来,你只需要做:
git cherry-pick 162f833c

相关问题