如何将使用"git replace"编辑的历史记录推送到远程 [英] How to push history edited with 'git replace' to remote

查看:96
本文介绍了如何将使用"git replace"编辑的历史记录推送到远程的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个具有如下历史记录的遥控器:

I have a remote with a history that looks like this:

如您所见,O和P是合并提交,并且它们都关闭了旧分支,所以现在只有一个分支.

As you can see O and P are merge commits and both of them closed their old branch so now there's only one branch.

我想将C-D-E-G-J-K-L-N压缩为一个提交,将F-H-I-M压缩为另一个提交,因为它们只是使历史混乱的微小提交.

I want to squash C-D-E-G-J-K-L-N into one commit and F-H-I-M into an other commit because they are just tiny commits cluttering the history.

我在本地设法使用 John O'M的答案中所述的方法来压缩C-D-E-G-J-K-L-N.这个问题,例如:

Locally I managed to squash C-D-E-G-J-K-L-N using the method described in the answer by John O'M. to this question, like this:

git checkout -b squashing-1 N
git reset --soft C~
git commit -m "Squashed history"
git replace N [ID_of_the_commit_i_just_made]

这有效,从主分支本地git log正确报告Q,P,O,X,M,I等(X是新压缩的提交).

and this works, locally git log from main-branch correctly reports Q, P, O, X, M, I, etc. (X is the new squashed commit).

从这里开始,下一步是(1)签出主分支并合并更改,(2)删除临时本地分支,然后(3)将更改推送到远程仓库.但是(1)和(3)报告已经是最新的所有内容都是最新的,因为树并没有实际变化,这恰恰是所有这些.

From here the next steps would be to (1) check out the main branch and merge in the changes, (2) delete the temporary local branch, then (3) push the changes to the remote repo. But (1) and (3) report Already up to date or Everything is up to date since there are no actual changes to tree which is exactly the point of all this.

我也尝试过使用git push --force origin main-branchgit push --force-with-lease origin main-branch,但是我得到了相同的结果:一切都是最新的.

I've tried using git push --force origin main-branch and git push --force-with-lease origin main-branch too but i got the same result: Everything is up to date.

我如何正确合并这些历史记录更改并将其推送到BitBucket,而不必重新创建整个存储库?

推荐答案

您基本上可以选择:您是想让所有人使用替换引用,还是希望重写整个存储库并让每个人都有一个从旧存储库"切换到新存储库"的大卖旗日?两种方法都不是特别有趣或无利可图. :-)

You essentially have a choice to make: do you wish to make everyone use the replacement references, or do you prefer to rewrite the entire repository and make everyone have a big flag-day during which they switch from "old repository" to "new repository"? Neither method is particularly fun or profitable. :-)

git replace的作用是在Git存储库中添加一个新对象,并在refs/replace/命名空间中为其命名.该名称空间中的名称是新对象替换的对象的哈希ID.例如,如果您要替换提交1234567...,则新对象的名称(其ID不是1234567...,具体来说,它是fedcba9...)是refs/replace/1234567....

What git replace does is to add a new object into the Git repository and give it a name in the refs/replace/ name-space. The name in this name-space is the hash ID of the object that the new object replaces. For instance, if you're replacing commit 1234567..., the name of the new object (whose ID is not 1234567...—for concreteness, let's say it's fedcba9... instead) is refs/replace/1234567....

Git的 rest 在查找对象时,首先检查是否有refs/replace/<hash-id>对象.如果是这样(并且不禁止替换),那么其余的Git会返回refs/replace/名称指向的对象,而不是实际的对象.因此,当Git的其他部分读取某些内容为我的父提交为1234567..."的提交时,Git的另一部分将查找1234567...,看到refs/replace/1234567...存在,并返回对象fedcba9....然后,您会看到替换项.

The rest of Git, when looking for objects, checks first to see if there is a refs/replace/<hash-id> object. If so (and replacing is not disabled), the rest of Git then returns the object to which the refs/replace/ name points, instead of the actual object. So when some other part of Git reads some commit that says "my parent commit is 1234567...", that other part of Git goes to find 1234567..., sees that refs/replace/1234567... exists, and returns object fedcba9... instead. You then see the replacement.

但是,如果没有具有引用refs/replace/1234567...,则您的Git永远不会交换替换对象. (无论您是否拥有替换对象,这都是事实.是引用本身导致替换发生.拥有引用可确保您拥有该对象.)

If you do not have the reference refs/replace/1234567..., though, your Git never swaps in the replacement object. (This is true whether or not you have the replacement object. It's the reference itself that causes the replacement to occur. Having the reference guarantees that you have the object.)

因此,对于某些 other Git要执行相同的替换过程,您必须refs/replace/引用传递给其他Git.

Hence, for some other Git to execute this same replacement process, you must deliver the refs/replace/ reference to that other Git.

通常,您可以通过以下方式推送此类对象:

In general, you would push such objects with:

git push <repository> 'refs/replace/*:refs/replace/*'

(或具体列出您希望推送的一个替换引用).要获取这些对象:

(or specifically list the one replace reference you wish to push). To fetch these objects:

git fetch <repository> 'refs/replace/*:refs/replace/*'

(您可以将此获取refspec添加到每个克隆中的fetch配置中.然后使用git fetchgit fetch <repository>会自动拾取所有推送的新替换对象.推送仍然很麻烦,当然,此步骤必须在每个新克隆上重复.)

(You can add this fetch refspec to the fetch configuration in each clone. Using git fetch or git fetch <repository> will then automatically pick up any new replacement objects pushed. Pushing is still a pain, and of course this step has to be repeated on each new clone.)

请注意,此处的refspec均未设置强制标志.如果发生这种情况,是否要强制覆盖现有的refs/replace/引用由您决定.

Note that neither refspec here sets the force flag. It's up to you whether you want to force-overwrite existing refs/replace/ references, should such a thing happen.

或者,一旦替换到位,就可以运行存储库复制操作-这就是说,逐个提交副本,而不是像git clone --mirror这样的快速副本,例如git filter-branch.如果在不禁用替换的情况下运行了此复制操作,则将复制替换的对象;而是复制它们的替换.因此:

Alternatively, once you have replacements in place, you can run a repository-copying operation—by this, I mean a commit-by-commit copy, not a fast copy like git clone --mirror—such as git filter-branch. If this copying operation is run without disabling replacements, the replaced objects are not copied; instead, their replacements are copied. Hence:

git filter-branch --tag-name-filter cat -- --all

在复制的存储库中永久具有水泥置换"的副作用.然后,您可以丢弃所有原始引用所有替换引用. (执行此操作的简单方法是克隆已过滤的存储库.)

has the side effect of "cementing replacements" forever in the copied repository. You may then discard all the original references and all the replacement references. (The easy way to do this is to clone the filtered repository.)

当然,因为这是一个新的不同的存储库,所以它与原始存储库或其任何克隆版本不兼容.但是,它不再需要对refs/replace/命名空间进行仔细的协调(因为它不再具有任何替换对象!).

Of course, since this is a new and different repository, it is not compatible with the original repository or any of its clones. But it no longer requires careful coordination of the refs/replace/ name-space (since it no longer has any replacement objects!).

这篇关于如何将使用"git replace"编辑的历史记录推送到远程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆