重新设置单个Git提交


116

有没有一种方法可以将单个提交从一个分支重新部署到另一个分支?

我有这个分支结构:

-- -- -- -- -- (Master)
            \
              -- -- -- -- -- XX (Feature-branch)

我要做的就是将最后一次提交重新部署Feature-branch到master上,然后回滚Feature-branch一次提交。

-- -- -- -- -- XX (Master)
            \
              -- -- -- -- -- (Feature-branch)

我怎么做?


3
如果您可以将任何数量的提交作为基准,那么为什么要要求对单个基准进行重新基准呢?如果我可以在SO中提出问题,我会问重新定基(单次提交)和选择樱桃有何区别?
2013年

9
因为我不知道存在摘樱桃的行为,所以我做“分支上的事”,“获取不同分支上的修复请求”,“修复”,“提交到错误的分支”,“ D'OH!”。足以问这个问题是有用的。
凯文·迈尔

Answers:


116

您可以选择XX掌握。

git checkout master
git cherry-pick <commit ID of XX>

并使用git reset从功能分支中删除最后一次提交。

git checkout Feature-branch
git reset --hard HEAD^

63
比起包含“樱桃挑剔”的问题,一个专门称为“ git rebase ...”的问题如何得到公认的答案,这是一个完全不同的概念,有时本身就被认为是不干净的?
Bondax

1
不知道这是否相关,但是我想重新建立的提交已移动了一些文件,cherry-pick并使它们看起来好像是从旧位置删除并在新位置创建的。我想rebase应该会解决这个问题,但是现在我已经向上游推进,所以我无法测试。无论如何,请提防类似情况。
waldyrious 2015年

注意:要推动Feature-branch对原点的更改,您将需要更改原点,git push -f origin Feature-branch因为您Feature-branch现在被认为是origin/Feature-branch
jojo

1
此解决方案与CharlesB的解决方案之间有什么实际区别?
Lii

96
git rebase --onto master branch~1 branch 

这表示“在主分支的顶端重新分配分支的最后分支之间的提交范围(即XX提交)”

branch提交后移动此操作提示后XX,因此您需要使用

git checkout branch
git reset --hard branch@{1}^

上面写着“将分支提示重置为先前状态之前的提交”

因此,选择樱桃是一个更简单的解决方案...


5
这似乎对我不起作用,我在XX之前丢失了提交,并且分支已通过一次提交重新建立为母版的基础,但是我以前从未使用--onto过,所以我可能做错了什么。顺便说一句,OP说要改头换面,但似乎他想选个樱桃。
tewe

1
我的错误,rebase确实确实在master上移动了分支,必须将其重置
CharlesB 2013年

1
此解决方案与tewe解决方案之间的实际区别是什么?
Lii

1
@Lii我唯一看到的是它使用3步而不是4步
CharlesB

51

实际上很简单。解决方案是进行交互式基准,并“删除”所有您不想包括在基准中的提交。

git rebase -i <target_branch>target_branch您要基于的分支在哪里

然后,您将编辑打开的文件,pick您想要的提交以及drop(或d简称为)您不想带来的所有提交。


6
IMO是一个更好的解决方案,它实际上解决了这个问题。
加布里埃尔·奥西罗(GabrielOshiro)

考虑到它的通用性,直观性和简短性,这应该是公认的解决方案。
Pablo Arias

1

@Charles的响应是正确的。无论如何,我最终使用了很多次,大部分都是为了重新配置项目中的特定配置

  * a8f9182(HEAD->生产)生产配置
  | * daa18b7(预)预生产配置
  | /  
  | * d365f5f(本地)本地配置
  | /  
  * 27d2835(dev)惊人的新功能将拯救世界
* | 56D2467(大师)无聊的最新艺术作品
| /

我为此创建了一个新命令:

$ cat〜/ bin / git-rebaseshot 
COMMIT = $ 1
DEST = $ {2:-HEAD}
git rebase $ {COMMIT} ^ $ {COMMIT}-到$ DEST

通常,您想自动完成该命令的分支名称,因此可以添加该命令来获取此功能(添加到.bashrc或.profile中):

_git_rebaseshot() 
{ 
    __gitcomp_nl“ $(__ git_refs)”
}

git autocomplete将搜索它

您可以使用以下命令:

# rebase config on prepro on actual HEAD
$ git rebaseshot prepro 
# rebase config on local onto dev
$ git rebaseshot local dev
# rebase production config on master
$ git rebaseshot pro master

当正确划分要素时,可能性无穷无尽。

* a8f9182(HEAD-> postgres)BBDD配置
* a8f9182(本地)本地配置
* a8f9182(调试)日志级别配置
* a8f9182(dev)新功能
|

我想这就是被子们喜欢做的事情。

无论您提供什么sha / ref,此命令都可以使用:

$ git rebaseshot <Feature branch> master
$ git rebaseshot <commit of XX> master

//,您可以链接到我们可以在实际操作中看到的任何项目吗?
内森·巴桑内塞

就其本质而言,可用于rebaseshot的分支不会在本地回购之外提交。只需在master之上创建几个分支(日志级别,数据库连接,配置),然后在它们之间使用命令。看到效果很简单。
albfan

//,我遇到了一些问题。我会再试一次。
内森·巴桑尼斯

0

这是另一个选择:

  1. 确保您的遥控器具有功能分支的副本
  2. 删除本地要素分支
  3. 创建并签出一个新分支,其名称与您刚从母版中删除的旧功能分支同名
  4. 从所需功能分支的远程副本中挑选一个提交。

命令如下:

git checkout Feature-branch
git push -u origin HEAD
git checkout master
git branch -D Feature-branch
git checkout -b Feature-branch
git cherry-pick HASH-OF-XX

这不是rebase命令,而是精神上的rebase。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.