使用Git将最近的提交移动到新分支

Mar*_*osi 4647 git branching-and-merging git-branch

我想把我已经承诺掌握的最后几个提交移动到一个新的分支,然后在完成这些提交之前把主人带回去.不幸的是,我的Git-fu还不够强大,有什么帮助吗?

即我怎么能从这里走出来

master A - B - C - D - E
Run Code Online (Sandbox Code Playgroud)

这个?

newbranch     C - D - E
             /
master A - B 
Run Code Online (Sandbox Code Playgroud)

syk*_*ora 5947

搬到新的分支机构

警告:此方法有效,因为您使用第一个命令创建新分支:--keep.如果要将提交移动到现有分支,则需要在执行之前将更改合并到现有分支中git checkout(请参阅下面的移动到现有分支).如果您不先合并更改,它们将会丢失.

除非涉及其他情况,否则可以通过分支和回滚轻松完成.

git checkout existingbranch
git merge master         # Bring the commits here
git checkout master
git reset --keep HEAD~3  # Move master back by 3 commits.
git checkout existingbranch
Run Code Online (Sandbox Code Playgroud)

但要确保要返回多少次提交.或者,您可以代替git stash提供您想要在(/ current)分支上"恢复" 的提交(或者像origin/master这样的引用)的哈希,例如:

git branch newbranch      # Create a new branch, containing all current commits
git reset --keep HEAD~3   # Move master back by 3 commits (Make sure you know how many commits you need to go back)
git checkout newbranch    # Go to the new branch that still has the desired commits
# Warning: after this it's not safe to do a rebase in newbranch without extra care.
Run Code Online (Sandbox Code Playgroud)

*1您只会从主分支"丢失"提交,但不要担心,您将在newbranch中进行这些提交!

警告:对于Git 2.0及更高版本,如果您稍后--hard在原始(git branch newbranch)分支上使用新分支,则HEAD~3在rebase期间可能需要一个显式选项以避免丢失结转提交.拥有origin/master一套使这个可能性比较大.有关详细信息,请参阅John Mellor的答案.

转移到现有分支

如果要将提交移动到现有分支,它将如下所示:

git reset --keep a1b2c3d4
Run Code Online (Sandbox Code Playgroud)

  • 特别是,*不要*尝试回到上次将提交推送到另一个存储库的位置,而另一个存储库可能是其他人可能已经提取的. (234认同)
  • 另请注意:请勿对工作副本中未提交的更改执行此操作!这只是咬我!:( (208认同)
  • @Jonathan Dumaine:因为我在从旧分支中删除提交之前创建了新分支.他们仍然在新的分支机构. (130认同)
  • 想知道你是否可以解释为什么这有效.对我来说,你正在创建一个新的分支,从你仍在的旧分支中删除3个提交,然后检查你所创建的分支.那么你删除的提交如何神奇地出现在新的分支中? (97认同)
  • git中的分支只是指向历史提交的标记,没有任何克隆,创建或删除(标记除外) (81认同)
  • 为了避免将master重置为错误提交的一些风险,这个更精确地设置分支."git reset --hard 1a0c9b",其中"1a0c9b"是您希望返回的提交哈希的开始. (53认同)
  • 我将'git reset --hard HEAD~3'更改为'git reset --hard origin/master'.那么你不必知道你掌握多少提交.它会将您的本地主服务器与服务器上的主服务器同步. (31认同)
  • **这个答案导致提交丢失:**下次你`git rebase`时,3个提交将从`newbranch`中默默地丢弃.有关详细信息和更安全的替代方案,请参阅[我的回答](http://stackoverflow.com/a/36463546/691281). (16认同)
  • "如果你没有先合并你的更改,它们就会丢失." - 这不完全正确.提交只会变得分离.垃圾收集需要很长时间(大约1000次提交或者大约10000次?)所以你仍然可以恢复它们.通过记住SHA或使用`git reflog`或`git fsck --lost-found`找到它们.[有关丢失提交的更多信息](http://gitready.com/advanced/2009/01/17/restoring-lost-commits.html) (14认同)
  • 但那么你将如何将其推送到另一个存储库?当我在`git reset --hard HEAD~3`之后执行`git push`时,我被拒绝了. (13认同)
  • 如果你想推动master branch(或者你的回滚原始分支)使用`git push --force origin master`.如果您没有键入强制git将拒绝推送并将要求您从远程拉回滚提交. (13认同)
  • 是的,你做了,很可能是人们意外地犯了错误的分支,他们希望HARD删除那些提交后把它们放在另一个分支上,另一个分支很可能最终会合并到意外提交的那个,经过审查和测试 (8认同)
  • @AdamTuttle哦是的.但是无论如何,藏匿处工作得很好. (7认同)
  • 我知道了.分支是克隆当前所处状态的.由于某种原因,我假设这些提交不会被克隆,因为它们不在远程服务器上(太多git-svn哈哈).谢谢. (4认同)
  • 这就是我使用的:`git push --force -u origin master`然后`git push -u origin newbranch`. (4认同)
  • 主要和新分支的`git push --force -u origin`应该是答案的一部分 (4认同)
  • 为什么经常推荐`git reset --hard`?为什么不`git checkout head~3 .`(注意`.`或者你最终会在无头分支上)?(当然`head~3`可以用上面提到的替代品替换).似乎`checkout`更安全,因为它不会破坏你的历史.我错过了什么? (2认同)
  • 为什么你要进行不必要的检查并丢弃你的工作树?`git checkout -b newbranch; gitbranch -f master master~3`(或...`origin/master`)。 (2认同)
  • 如果可能的话,我想知道如何使用新的GitHub Desktop软件.对于某些事情我知道我在命令行的方式,但是在基于文本的环境中git太复杂了.既然可以使用可访问的,免费的,基于GUI的官方解决方案,我想使用它. (2认同)

Rya*_*ndy 975

对于那些想知道它为什么起作用的人(就像我一开始):

您想要返回到C,并将D和E移动到新分支.这是它最初的样子:

A-B-C-D-E (HEAD)
        ?
      master
Run Code Online (Sandbox Code Playgroud)

之后git branch newBranch:

    newBranch
        ?
A-B-C-D-E (HEAD)
        ?
      master
Run Code Online (Sandbox Code Playgroud)

之后git reset --hard HEAD~2:

    newBranch
        ?
A-B-C-D-E (HEAD)
    ?
  master
Run Code Online (Sandbox Code Playgroud)

由于分支只是一个指针,因此master指向最后一次提交.当你创建newBranch时,你只需要创建一个指向最后一次提交的新指针.然后使用git reset你将指针移回两次提交.但是既然你没有移动newBranch,它仍然指向它最初的提交.

  • 我还需要做一个`git push origin master --force`,以便在主存储库中显示更改. (46认同)
  • @John,那是胡说八道.在不知道你正在做什么的情况下进行重新定位会导致丢失.如果你丢失了提交,我很抱歉,但这个答案并没有丢失你的提交.请注意,`origin/master`不会出现在上图中.如果你推到'origin/master`然后进行上面的更改,那么事情会变得很有趣.但这是一个"博士,当我这样做时会受到伤害"这样的问题.原始问题的范围超出范围.我建议你写一些自己的问题来探索你的场景而不是劫持这个场景. (9认同)
  • **这个答案导致提交丢失:**下次你`git rebase`时,3个提交将从`newbranch`中默默地丢弃.有关详细信息和更安全的替代方案,请参阅[我的回答](http://stackoverflow.com/a/36463546/691281). (8认同)
  • @JohnMellor,您是正确的,在不带参数的情况下调用“git rebase”会启用“--fork-point”选项,这可能会导致提交丢失。在我看来,这是“git rebase”的一个缺陷。不过这和我上面的回答没有任何关系。在很多情况下,不带参数的 git rebase 可能会引起麻烦。这个故事的寓意(不幸的是)是不要在不传入分支的情况下调用“git rebase”,即使该分支已经是上游。在过去八年左右的时间里,Git 的可用性有了很大的提高,但这是它需要做更多工作的领域。 (2认同)

Iva*_*van 427

一般来说...

在这种情况下,sykora公开的方法是最佳选择.但有时并不是最容易的,也不是一般的方法.对于一般方法,使用git cherry-pick:

要实现OP想要的,它需要两个步骤:

第1步 - 注意哪些提交你想要的主人 newbranch

执行

git checkout master
git log
Run Code Online (Sandbox Code Playgroud)

注意你想要的哈希(比如3)提交newbranch.在这里我将使用:
C commit:9aa1233
D commit:453ac3d
E commit:612ecb3

注意:您可以使用前七个字符或整个提交哈希

第2步 - 把它们放在上面 newbranch

git checkout newbranch
git cherry-pick 612ecb3
git cherry-pick 453ac3d
git cherry-pick 9aa1233
Run Code Online (Sandbox Code Playgroud)

或(在Git 1.7.2 +上,使用范围)

git checkout newbranch
git cherry-pick 612ecb3~1..9aa1233
Run Code Online (Sandbox Code Playgroud)

git cherry-pick将这三个提交应用于newbranch.

  • 是不是OP试图移动_from_ master _to_ newbranch?如果你在master上进行挑选,那么你将添加到master分支 - 实际上是添加已经拥有的提交.并且它不会将任何一个分支头移回B.或者是否有一些微妙而酷的东西我没有得到? (13认同)
  • 樱桃采摘的顺序是否重要? (8认同)
  • 这是更好的答案.这样您就可以将提交移动到任何分支. (7认同)
  • 如果您在创建新功能分支时意外提交了错误的非主分支,则此方法非常有效. (6认同)
  • 在某些情况下,+1是有用的方法.如果您只想将自己的提交(与其他人一起穿插)放入新分支,那么这很好. (5认同)
  • 关于git cherry-pick的信息很不错,但是这篇文章中的命令不起作用.1)'git checkout newbranch'应该是'git checkout -b newbranch',因为newbranch尚不存在; 2)如果从现有的主分支中检出newbranch,那么ALREADY会包含这三个提交,因此选择它们是没有用的.在一天结束时获得OP想要的东西,你仍然需要做某种形式的重置 - 硬头HEAD. (3认同)
  • 我无法使用樱桃挑选范围,在其中一个提交中得到"错误:无法应用c682e4b ......",但是当每次提交一次使用樱桃挑选时,它工作正常(我有在错误之后做git cherry-pick --abort).评论因为我认为那些是等价的.这是在git版本2.3.8(Apple Git-58) (3认同)
  • 对于参考,你通常可以使用3-5个六角形; 然而,很多需要Git唯一地识别提交.另外,你可以使用`master~3..master`来引用`master`的最后3次提交而不是哈希. (3认同)
  • @konpsych我相信订单很重要.您希望首先执行最早的提交. (3认同)
  • 这些对我来说失败了,但按照“正确”的顺序进行,即。按照提交的时间顺序,为我工作:`gitcherry-pick 9aa1233 453ac3d 612ecb3` (3认同)
  • 如果樱桃采摘是最后的N次提交,那么你可以将你的主HEAD移回w /`git reset --hard HEAD~N` (2认同)
  • 没有为我工作。错误消息,“没有添加到提交”。以前的樱桃挑选现在是空的。允许为空或继续。无论如何,它似乎不起作用,提交没有被转移。 (2认同)
  • 第二个樱桃挑选示例是不正确的.`612ecb3..9aa1233`表示所有提交但不包括`612ecb3`直到并包括`9aa1233`.要获得所有三个提交,你需要`cherry-pick 612ecb3~1..9aa1233`. (2认同)
  • 使用“cherry-pick”复制它们后,将它们从原始分支中删除的最佳方法是什么?我通过“git rebase -i”删除提交来做到这一点,但想知道是否有更好的方法。 (2认同)

ara*_*aer 306

另一种方法是使用2个命令.还可以保持当前工作树的完整性.

git checkout -b newbranch # switch to a new branch
git branch -f master HEAD~3 # make master point to some older commit
Run Code Online (Sandbox Code Playgroud)

旧版本 - 在我了解之前git branch -f

git checkout -b newbranch # switch to a new branch
git push . +HEAD~3:master # make master point to some older commit 
Run Code Online (Sandbox Code Playgroud)

能够push.是一个不错的把戏就知道了.

  • 我不知道为什么这个评级不高.死简单,没有git重置的小但潜在的危险 - 硬. (29认同)
  • @Godsmith我的猜测是人们更喜欢三个简单的命令,而不是两个稍微模糊的命令.此外,最高投票的答案通过首先显示的性质得到更多的赞成. (4认同)
  • @GerardSexton` .`是现任导演.git可以推送到REMOTES或GIT URL."本地目录的路径"支持Git URL语法.请参阅`git help clone`中的GIT URLS部分. (2认同)

Joh*_*lor 295

以前的大多数答案都是危险错误的!

不要这样做:

git branch -t newbranch
git reset --hard HEAD~3
git checkout newbranch
Run Code Online (Sandbox Code Playgroud)

当你下次运行git rebase(或git pull --rebase)时,这3个提交将被默默地丢弃newbranch!(见下面的解释)

而是这样做:

git reset --keep HEAD~3
git checkout -t -b newbranch
git cherry-pick ..HEAD@{2}
Run Code Online (Sandbox Code Playgroud)
  • 首先,它丢弃最近的3个提交(--keep就像是--hard,但更安全,因为失败而不是丢弃未提交的更改).
  • 然后它就会离开newbranch.
  • 然后樱桃挑选那3个提交回来newbranch.由于它们不再被分支引用,它通过使用git的reflog来实现:HEAD@{2}HEAD用于引用2个操作之前的提交,即在我们签出之前newbranch和2.用于git reset丢弃3个提交之前.

警告:默认情况下启用reflog,但如果您手动禁用它(例如,通过使用"裸"git存储库),则运行后将无法恢复3次提交git reset --keep HEAD~3.

不依赖于reflog的替代方案是:

# newbranch will omit the 3 most recent commits.
git checkout -b newbranch HEAD~3
git branch --set-upstream-to=oldbranch
# Cherry-picks the extra commits from oldbranch.
git cherry-pick ..oldbranch
# Discards the 3 most recent commits from oldbranch.
git branch --force oldbranch oldbranch~3
Run Code Online (Sandbox Code Playgroud)

(如果你愿意,你可以写@{-1}- 以前签出的分支 - 而不是oldbranch).


技术说明

为什么git rebase在第一个例子之后丢弃3个提交?这是因为git rebase没有参数--fork-point默认启用该选项,它使用本地reflog尝试对强制推送的上游分支进行强制.

假设你在包含提交M1,M2,M3的情况下分支origin/master,然后自己做三次提交:

M1--M2--M3  <-- origin/master
         \
          T1--T2--T3  <-- topic
Run Code Online (Sandbox Code Playgroud)

但后来有人通过强制推动origin/master删除M2来重写历史记录:

M1--M3'  <-- origin/master
 \
  M2--M3--T1--T2--T3  <-- topic
Run Code Online (Sandbox Code Playgroud)

使用本地reflog,git rebase可以看到您从origin/master分支的早期版本分叉,因此M2和M3提交实际上不是主题分支的一部分.因此,它合理地假设,由于M2已从上游分支中删除,因此在主题分支重新定位后,您不再需要在主题分支中使用它:

M1--M3'  <-- origin/master
     \
      T1'--T2'--T3'  <-- topic (rebased)
Run Code Online (Sandbox Code Playgroud)

这种行为是有道理的,并且在变基时通常是正确的做法.

所以以下命令失败的原因:

git branch -t newbranch
git reset --hard HEAD~3
git checkout newbranch
Run Code Online (Sandbox Code Playgroud)

是因为他们让reflog处于错误的状态.Git认为newbranch已经在包含3次提交的修订版中分离了上游分支,然后reset --hard重写上游的历史记录以删除提交,因此下次运行git rebase它时会丢弃它们,就像从上游删除的任何其他提交一样.

但在这种特殊情况下,我们希望将这3个提交视为主题分支的一部分.为了实现这一点,我们需要在不包含3次提交的早期版本中分离上游.这就是我建议的解决方案,因此他们都将reflog保持在正确的状态.

有关详细信息,请参阅定义--fork-pointgit的底垫混帐合并基础文档.

  • 这个答案说"不要这样做!" 高于没有人建议的事情. (12认同)
  • 大多数人不会重写已发表的历史,尤其是在“master”上。所以不,他们没有危险的错误。 (8认同)
  • @Kyralessa,如果你有`git config --global branch.autosetuprebase always` set,你在`git branch`中引用的`-t`会隐式发生.即使你不这样做,我[已经解释过](http://stackoverflow.com/questions/1628563/move-the-most-recent-commits-to-a-new-branch-with-git/36463546?noredirect = 1#comment60571505_6796816)如果您在执行这些命令后设置跟踪,则会出现同样的问题,因为OP可能会打算提出问题. (4认同)
  • 太糟糕了,这不是公认的答案。正如您所描述的,我按照已接受的答案中的步骤操作并丢失了 6 次提交! (3认同)
  • @RockLee,是的,解决这种情况的一般方法是从一个安全的起点创建一个新分支(newbranch2),然后从樱桃中挑选您要保留的所有提交(从badnewbranch到newbranch2)。Cherry-picking将为提交赋予新的哈希,因此您将能够安全地为newbranch2重新设置基础(并且现在可以删除badnewbranch)。 (2认同)
  • @Walf,你误解了:_git rebase_旨在对上次重写历史的上游做好准备.不幸的是,这种稳健性的副作用会影响每个人,即使他们和他们的上游都没有重写历史. (2认同)
  • 您还可以在运行“git rebase”时使用“--no-fork-point”。 (2认同)
  • 不使用相对修订格式,只需采用当前的 HEAD 修订版本,例如 `aaaaaa`,master `bbbbbb` 的新 HEAD,以及 `bbbbbb` 之后的修订版本,例如 `cccccc`,然后执行 `git reset --keep bbbbbb `; `git checkout -t -b newbranch` ; `gitcherry-pick cccccc..aaaaaa` (2认同)
  • 您的“不依赖于 reflog 的替代方案”不与“git Push”互操作:无论我尝试推送到远程存储库的哪个分支,它都会给出错误:旧的或新的。不看好 (2认同)
  • @尤金·格。Philippov 同样在这里,git 不断告诉我需要“git push”——这反过来又告诉我一切都已经是最新的,因此什么也不做。接下来,git 告诉我“git push”,循环重复。我确信它被命名为“git”是有原因的。我不得不使用“git Push origin”来强制合作。 (2认同)
  • 我**只有一项承诺**要移动。对于这种情况很重要:在第一步中使用“HEAD~1”,但在最后一步中保留“..HEAD@{2}”。否则,您会收到 **cherry-pick** 失败错误。(当我之前尝试`..HEAD@{0}`或`..HEAD@{1}`时,我收到了cherry-pick错误并且**我认为我的提交丢失了**。)。。。。。。。。。。因此,请使用以下步骤: `git reset --keep HEAD~1` `git checkout -t -b newbranch` `gitcherry-pick ..HEAD@{2}` (2认同)

Sla*_*lam 109

使用git stash的更简单的解决方案

如果:

  • 你的主要目的是回滚master,和
  • 您希望保留文件更改,但不要特别关心错误的提交消息,以及
  • 你还没推,而且
  • 您希望这很简单,并且不会出现临时分支,提交哈希和其他令人头疼的问题

然后以下更简单(从master具有三个错误提交的分支开始):

git reset HEAD~3
git stash
git checkout newbranch
git stash pop
Run Code Online (Sandbox Code Playgroud)

这是做什么的,按行号

  1. 撤消最后三次提交(及其消息)master,但保留所有工作文件
  2. 存储所有工作文件更改,使master工作树完全等于HEAD~3状态
  3. 切换到现有分支 newbranch
  4. 将隐藏的更改应用于您的工作目录并清除存储

您现在可以使用git add,并git commit像往常一样.所有新提交都将添加到newbranch.

这不做什么

  • 它不会让随机的临时分支混乱你的树
  • 它不会保留错误的提交和提交消息,因此您需要向此新提交添加新的提交消息

目标

OP表示目标是"在做出这些提交之前将主人带回来"而不会丢失更改,这个解决方案就是这样做的.

我每周至少做一次,因为我不小心做了新的提交master而不是develop.通常我只有一次提交回滚,在这种情况下使用git reset HEAD^第1行是一种简单的方法来回滚一次提交.

如果您将master的更改推送到上游,请不要这样做

其他人可能已经取消了这些变化.如果你只是重写你的本地主人,当它被推向上游时没有任何影响,但是将重写的历史推送给协作者可能会引起麻烦.

  • 这应该是公认的答案.它简单易懂,易于记忆 (7认同)
  • 如果“newbranch”尚不存在,那么您可以使用此命令在重置后将未暂存的更改移动到新分支,而无需存储:`git checkout -b newbranch` (5认同)
  • 我认为我们是完全典型的,"我错误地提交给主人"这是最常见的用例,需要恢复少数或更少的提交.幸运的是,这个解决方案非常简单,我现在已经记住了. (4认同)
  • 谢谢,很高兴我阅读了过去/通读本文,因为这对我来说也是一个很常见的用例。我们是如此不典型吗? (2认同)
  • 如果您的 CLI(命令行)历史记录中碰巧有提交消息,您也可以轻松取回它们。我碰巧同时使用了“git add”和“git commit”命令,所以我所要做的就是点击向上箭头并输入几次然后繁荣!一切都回来了,但现在在正确的分支上。 (2认同)

Suk*_*ima 30

这不会在技术意义上"移动"它们,但它具有相同的效果:

A--B--C  (branch-foo)
 \    ^-- I wanted them here!
  \
   D--E--F--G  (branch-bar)
      ^--^--^-- Opps wrong branch!

While on branch-bar:
$ git reset --hard D # remember the SHAs for E, F, G (or E and G for a range)

A--B--C  (branch-foo)
 \
  \
   D-(E--F--G) detached
   ^-- (branch-bar)

Switch to branch-foo
$ git cherry-pick E..G

A--B--C--E'--F'--G' (branch-foo)
 \   E--F--G detached (This can be ignored)
  \ /
   D--H--I (branch-bar)

Now you won't need to worry about the detached branch because it is basically
like they are in the trash can waiting for the day it gets garbage collected.
Eventually some time in the far future it will look like:

A--B--C--E'--F'--G'--L--M--N--... (branch-foo)
 \
  \
   D--H--I--J--K--.... (branch-bar)
Run Code Online (Sandbox Code Playgroud)


teh*_*aus 24

要在不重写历史记录的情况下执行此操作(即,如果您已经推送了提交):

git checkout master
git revert <commitID(s)>
git checkout -b new-branch
git cherry-pick <commitID(s)>
Run Code Online (Sandbox Code Playgroud)

然后可以无力推动两个分支!

  • 我不遵循你的论点 - 这个答案的要点是你不是在改变历史,只是添加新的提交(有效地撤销重做的改变).这些新提交可以正常推送和合并. (5认同)

Sai*_*pta 17

最简单的方法:

1.master分支重命名为您的newbranch(假设您在master分支上):

git branch -m newbranch
Run Code Online (Sandbox Code Playgroud)

2.master从您希望的提交创建分支:

git checkout -b master <seven_char_commit_id>
Run Code Online (Sandbox Code Playgroud)

例如 git checkout -b master a34bc22

  • 这不会弄乱远程上游分支吗?“newbranch”现在不是指向“origin/master”吗? (4认同)
  • 喜欢这个解决方案,因为您不必重写 git 提交标题/描述。 (2认同)

Dar*_*low 13

只是这种情况:

Branch one: A B C D E F     J   L M  
                       \ (Merge)
Branch two:             G I   K     N
Run Code Online (Sandbox Code Playgroud)

我表演了:

git branch newbranch 
git reset --hard HEAD~8 
git checkout newbranch
Run Code Online (Sandbox Code Playgroud)

我期望提交我将成为HEAD,但现在提交L就是......

为了确保在历史上的正确位置,它更容易使用提交的哈希

git branch newbranch 
git reset --hard #########
git checkout newbranch
Run Code Online (Sandbox Code Playgroud)


小智 11

总长DR

git checkout branch_to_remove_commits
git reset --hard ${hash_of_new_tip}
git checkout -b branch_to_store_commits
# Move commits (single hash, list of hashes or range ffaa..ffoo) 
git cherry-pick ${commit_hash}
git push --set-upstream origin branch_to_store_commits
# Switch back to last branch
git checkout -
git push -f
Run Code Online (Sandbox Code Playgroud)

为我

git log --pretty=oneline -n ${NUMBER}
Run Code Online (Sandbox Code Playgroud)

最适合识别有问题的提交哈希。


Sha*_*jib 9

如果您只需要将所有未推送的提交移动到新分支,那么您只需要,

  1. 从当前分支创建一个新分支git branch new-branch-name

  2. 推送你的新分支git push origin new-branch-name

  3. 您的旧(当前)分支恢复到上次推送/稳定状态:git reset --hard origin/old-branch-name

有些人也有其他upstreams而不是origin,他们应该使用适当的upstream


pan*_*kaj 6

只需我使用的 3 个简单步骤,您就可以做到这一点。

1)在您想要提交最近更新的地方创建新分支。

git branch <branch name>

2) 查找新分支上提交的最近提交 ID。

git log

3) 复制该提交 ID,请注意,最近的提交列表位于顶部。这样你就可以找到你的提交。您也可以通过消息找到此信息。

git cherry-pick d34bcef232f6c...

您还可以提供一些提交 ID 范围。

git cherry-pick d34bcef...86d2aec

现在你的工作完成了。如果你选择了正确的 id 和正确的分支,那么你就会成功。所以在做这件事之前要小心。否则可能会出现另一个问题。

现在您可以推送您的代码

git push


ras*_*hok 5

1) 创建一个新分支,将所有更改移动到 new_branch。

git checkout -b new_branch
Run Code Online (Sandbox Code Playgroud)

2)然后回到旧分支。

git checkout master
Run Code Online (Sandbox Code Playgroud)

3)进行git rebase

git rebase -i <short-hash-of-B-commit>
Run Code Online (Sandbox Code Playgroud)

4)然后打开的编辑器包含最后3次提交信息。

...
pick <C's hash> C
pick <D's hash> D
pick <E's hash> E
...
Run Code Online (Sandbox Code Playgroud)

5)在所有这 3 次提交中更改pick为。drop然后保存并关闭编辑器。

...
drop <C's hash> C
drop <D's hash> D
drop <E's hash> E
...
Run Code Online (Sandbox Code Playgroud)

6) 现在最后 3 个提交已从当前分支 ( master) 中删除。现在用力推动分支,并+在分支名称前加上符号。

git push origin +master
Run Code Online (Sandbox Code Playgroud)


Iva*_*van 5

我该如何去

A - B - C - D - E 
                |
                master
Run Code Online (Sandbox Code Playgroud)

对此吗?

A - B - C - D - E 
    |           |
    master      newbranch
Run Code Online (Sandbox Code Playgroud)

用两个命令

  • git branch -m主newbranch

给予

A - B - C - D - E 
                |
                newbranch
Run Code Online (Sandbox Code Playgroud)

  • git分支主管B

给予

A - B - C - D - E
    |           |
    master      newbranch
Run Code Online (Sandbox Code Playgroud)


Dav*_*dze 5

我很惊讶没有人推荐这种方式:

git checkout master
git checkout <commit hash from which you want to split>
git checkout -b new_branch
git rebase master
git checkout master
git reset --hard <commit hash you splitted>
Run Code Online (Sandbox Code Playgroud)

解释:

  1. 步骤我们检查我们想要拆分的提交
  2. 然后从这个提交创建一个新分支
  3. 执行 rebase 将同步 new_branch 和 master。所以现在我们有两个具有相同提交的相同分支
  4. 通过在 master 上重置,我们清理分割后的最后提交
  5. 项目清单