git - 恢复分支看起来像 master?

git - revert branch to look like master?

我有两个分支 developmaster。开发中有很多 master 中没有的提交。尽管我需要使 develop 分支看起来与 master 完全相同。为了保留 develop 中发生的所有更改,我将从 develop 创建新分支,这样所有这些更改都不会丢失。

但是在完成 develop 的 "copy" 之后,我如何才能安全地重置或恢复到 master 的样子?

我看到了这个:

所以要重置,我可以这样做:

git checkout develop
git reset --hard master

但问题是 develop 分支已经被推送到远程并且其他人已经拉 develop 了。

也许有更安全的方法使用恢复或其他方式来做到这一点?但我想恢复(如果可能)以恢复到 master 状态,而不是手动选择每个提交,因为一些最新的提交需要保留在 develop 中,因为它们来自 master(修补程序)。

所以 develop 上的提交历史看起来像这样(最顶层意味着按日期最新提交):

commit hotfix2 - in both develop and master
some other commits that are only in develop
commit hotfix1 - in both develop and master
some commits that are only in develop
all commits that came when develop was created from master

以非破坏性方式撤消提交的标准过程是使用 git revert。该命令基本上采用目标提交的反向差异并尝试应用它。所以你得到一个新的提交来撤销所有的更改。

为了一次撤消多个提交,您还可以指定一个提交范围。鉴于您只有两个范围要撤消(那些修补程序之间的范围),这实际上是可管理的。

您还可以使用标志 --no-commit-n 自动创建提交。这允许您将多个 git revert -n <commit> 命令一个接一个地链接起来,而无需为每个命令创建还原提交。然后,当您完成选择要撤消的所有提交或提交范围时,您可以进行一次合并它们的提交。

在你的情况下,因为你有另一个分支,它具有你想要将 develop 分支放入的确切(工作目录)状态,所以这样做要容易得多。您所要做的就是将 master 的工作树检出到您的 develop 分支并将该状态提交到 develop 分支。您可以使用 git checkout master -- . 来执行此操作。不幸的是,这不适用于 master 分支未知的路径。因此,如果您在 develop 分支中添加了新文件,这些文件将被保留,您必须单独删除它们。

相反,我们从 master 开始一个新分支(然后具有完全相同的内容),并重置该分支,使其基于 develop。这样,我们将工作目录状态从 master 保留下来,但提交将遵循 develop。之后,我们可以快进 develop 那个提交:

# checkout a new branch off master
git checkout -b new-develop master

# make a soft reset to develop
git reset --soft develop

# commit the changes
git commit

# get back to develop and fast forward
git checkout develop
git merge --ff-only new-develop
git branch -d new-develop

这将产生与将 git revert -ndevelop 独有的所有提交链接起来所得到的结果相同的结果。还有其他几种方法可以达到该状态,但这确实是最简单的方法。

不管你用什么方式达到这个状态,你都应该考虑之后进行合并。合并实际上不会做任何事情(因为两个分支具有相同的内容)但它会合并历史中的分支,所以你会看到它们实际上会收敛。

所以假设历史最初看起来是这样的:

                       master
                         ↓
* ------------ h1 ------ h2
 \              \         \
  * -- * -- * -- * -- * -- *
                           ↑
                         develop

你想把它变成这样:

                                master
                                  ↓
* ------------ h1 ------ h2 ----- M
 \              \         \      /  ↖
  * -- * -- * -- * -- * -- * -- F   develop

F 是我们在上面创建的修复提交。这假设您想要将 develop 合并到 mastergit merge develop while on master)然后快进 developgit merge master while develop) 从那时起重新开始开发工作。当然,如果你愿意的话,你也可以反着做。

或者,我们也可以一步完成合并 M 和修复 F。您可以有效地将 develop 合并到 master 中,并以最终得到 master 内容的方式合并所有内容。这看起来像这样:

                                master
                                  ↓
* ------------ h1 ------ h2 ---- FM
 \              \         \      /  ↖
  * -- * -- * -- * -- * -- * ---/   develop

您可以像这样手动到达那里:

# since we merge into master, we start there
git checkout master

# start the merge, but don’t attempt to fast-forward and do not
# commit the merge automatically (since we want to change it)
git merge --no-ff --no-commit develop

# reset the index that was prepared during the merge
git reset

# now checkout the files from master and commit the merge
git checkout master -- .
git add .
git commit

实际上,这种情况很常见,git merge 附带的合并策略正是这样做的。因此,我们可以只使用 ours 合并策略并丢弃我们合并到当前分支的任何内容,而不是上面的内容:

git checkout master
git merge -s ours develop

下面的命令将从 origin/master

中获取所有文件(当前分支中添加的新文件除外)
git checkout origin/master .

然后,可以使用git rm 删除新文件例如

git rm newfile