git:如何用另一个分支的内容重置分支?

git:如何用另一个分支的内容重置分支?,git,Git,我不知道如何将一个分支更新为与另一个分支相同。下面是一个例子: git init test; cd test echo apple >a; echo banana >b; git add a b; git commit -m 'A1/a:apple;b:banana' echo carrot >c; git add c; git commit -m 'A2/c:carrot' git checkout -b second HEAD^1 echo beets >b; ech

我不知道如何将一个分支更新为与另一个分支相同。下面是一个例子:

git init test; cd test
echo apple >a; echo banana >b; git add a b; git commit -m 'A1/a:apple;b:banana'
echo carrot >c; git add c; git commit -m 'A2/c:carrot'
git checkout -b second HEAD^1
echo beets >b; echo dandelion >d; git add b d; git commit -m 'B1/b:beets;d:dandelion'
在这一点上,我的历史如下:

A1-----A2     (master, contains a:apple, b:banana, c:carrot)
 \
  \----B1     (second, contains a:apple, b:beets, d:dandelion)
现在,我想向“第二个”分支添加一个提交,以使其内容与“主”分支匹配,即:

A1-----A2
 \
  \----B1--?--B2     (desired contents a:apple, b:banana, c:carrot)
我的问题是,我运行什么git命令来实现这一点?我想到的最接近的方法是:

git checkout master .
git commit -m B2
但是,虽然这会将b重置为香蕉并恢复c,但不会删除文件d。我还没能想出任何我想要的
git reset
变体。我不想做一个版本的
git revert
,因为在我的实际存储库中,分支上的历史记录比这个示例更复杂,分支可能包含合并


任何帮助都将不胜感激

我假设当前分支是第二个分支。如果您对
git reset--HARD master
不满意(因为如果
second
发布在任何地方,则需要强制推送),您可以通过
git revert B1
(或者如果不想列出所有提交(如B1),只需
git revert master..second
)撤消B1,然后
git merge master

git checkout second
git rm -rf .
git checkout master .
git commit -m B2
使用@StevenPenny idea和
我们的
策略,我想出了以下解决方案:

git checkout master
git checkout -b transfer_second_to_master
git merge -s ours second
git checkout second
git merge transfer_second_to_master
git branch -d transfer_second_to_master
这是对他们的
策略的一种模拟,是对我们的
策略的反转。现在,
git diff master second
没有给出任何东西,这意味着分支是相同的。

这听起来像是一个

更多信息

This resolves any number of heads, but the resulting tree of the merge is always that of the current branch head, effectively ignoring all changes from all other branches. It is meant to be used to supersede old development history of side branches. 这将解析任意数量的头,但合并的结果树始终是 当前分支头的更改,实际上忽略所有其他分支头的所有更改 分支机构。它是用来取代旧的发展历史的一方 分支机构。
听起来你只是想让branch
second
从A2开始。这很简单:

git branch -f second <commit-for-A2>
简单的方法 你几乎得到了正确的答案。解决方案是先删除所有文件,然后再从
master
签出

git checkout second
git rm -rf .
git checkout master .
git commit -m B2
这将创建一个带有新消息、作者和时间戳的新提交。如果你认为所有这些都是一样的,你最好的选择是

使用git reparent(无耻插头) 下载并安装到您的
$PATH
,然后

git checkout second
git branch parent
git reset --hard master
git reparent -p parent
git branch -d parent
说明:

  • 切换到要修改的分支(
    second
  • 保存指向当前提交的指针(
    parent
  • 指向我们想要结束的提交(
    master
  • 修改当前分支(
    second
    )以具有当前提交的内容,但具有给定的父级(
    parent
  • 删除保存的指针(
    parent
  • 以前

    • 现任分行:第二
    • git状态
      :清除
    变体1:未提及master(非常难看) 之后:

    A1-----A2      (master, contains a:apple, b:banana, c:carrot)
     \
      \----B1---B2 (second, contains a:apple, b:banana, c:carrot)
    
    A1-------A2    (master, contains a:apple, b:banana, c:carrot)
     \         \
      \----B1---B2 (second, contains a:apple, b:banana, c:carrot)
    
    • 当前分支机构:第二(ff)
    • git状态
      :清除
    • diff
      状态到
      master
      :清洁
    确认倒车作业:

    git reset --hard HEAD^
    git clean -f
    git branch -avv
    
    git reset --hard HEAD^
    git clean -f
    git branch -avv
    
    再次显示before状态

    这个变体有什么作用

    • git-read-tree
      将给定的其他提交(此处为
      master
      )读取到索引中
    • 当给出选项
      -u
      时,它会相应地更新工作树
    • 然后像往常一样将其提交到B1上
    • 但是,它不会添加对“合并”树的引用
    变量2:显示对主节点的合并引用(首选!) 对不起,我没有找到正确的方法。以下是一个解决方法:

    第一:进行虚拟合并

    git merge -s ours -m 'B2 dummy' master
    
    第二:将合并修复为正确的数据

    git read-tree -m -u master
    git commit --amend -m 'B2: copy of A2'
    
    第三:检查它是否真的匹配
    master

    git diff master
    
    之后:

    A1-----A2      (master, contains a:apple, b:banana, c:carrot)
     \
      \----B1---B2 (second, contains a:apple, b:banana, c:carrot)
    
    A1-------A2    (master, contains a:apple, b:banana, c:carrot)
     \         \
      \----B1---B2 (second, contains a:apple, b:banana, c:carrot)
    
    • 当前分支:第二个(ff,合并,第一个父级:B1)
    • git状态
      :清除
    • diff
      状态到
      master
      :清洁
    确认倒车作业:

    git reset --hard HEAD^
    git clean -f
    git branch -avv
    
    git reset --hard HEAD^
    git clean -f
    git branch -avv
    
    再次显示before状态,这是应该的

    这是如何工作的:

    • git read tree-m-u master
      重置合并信息,因此我们无法启动合并,读取树,然后提交此合并,很遗憾
    • 但是,我们希望使用选项
      -u
      ,因为这对于更新工作树至关重要。但是
      -u
      需要
      -m
      或类似的东西,这会使我们脱离合并模式
    • 因此,我们在之前进行了一次虚拟合并(并使用策略
      ours
      来防止合并冲突,这正是我们希望发生的错误事情)
    • 然后,我们根据需要使用
      git-read-tree
      从master读取状态
    • 现在我们
      修改
      合并到现在,最后修改,索引内容
    • 这将保留原始合并信息
    • 请注意,这是上游的
      ff
    这有什么问题

    • git commit
      是原子的。要么你有一个正确的状态,要么你没有
    • 然而,这引入了一种非原子的情况,在这种情况下,竞争条件(断电)会使您的本地git repo处于某种不需要的状态
    • 如果在自动设置中使用此策略,则这是不好的,例如,在发布(B1)后,应使用当前上游(主)重新启动以创建下一个发布(B2及更高版本)
    • 因此,变体2不能被视为这一问题的最后定论。是的,不知怎的,它是有效的,但它既不好,也不干净,也不完美
    其他解决方案似乎过于复杂。但也许我监督了一点

    • 或者使用完全不可理解的git管道命令自己创建正确的提交对象——这是一个不可能的解决方案,它应该易于理解和使用

    • 或者做一些非常复杂的分支,然后快进到分支,然后删除它——一个双重禁止,就像这个介绍一样