拉动后将已落实(但未推送)的移动更改为新分支


459

我已经做了很多工作(“您的分支要比'origin / master'提前37次提交。”)实际上应该已经进入了自己的分支,而不是进入了master。这些提交仅存在于我的本地计算机上,尚未推送到origin,但是情况有些复杂,因为其他开发人员一直在推送到origin/master我,而我撤消了这些更改。

如何将我的37个本地提交追溯地移动到新分支上?根据该文件,看来git rebase --onto my-new-branch master还是...origin/master应该这样做,但都只是给我的错误“致命的:需要一个单一版本”。 man git-rebase它没有提供有关修订的信息rebase,其示例也没有这样做,因此我不知道如何解决此错误。

(请注意,这与将现有未提交的工作移至Git中的新分支如何将我的本地未提交的更改合并到另一个Git分支不是重复的因为这些问题是针对本地工作树中未提交的更改,而不是涉及已在本地提交。)


查看此解决方案。似乎很容易清洁。
托尼

查看此解决方案。似乎很容易清洁。
托尼

Answers:


517

这应该很好,因为您尚未将提交推送到其他任何地方,并且可以在之后随意重写分支的历史记录origin/master。首先,我将运行一次git fetch origin以确保它origin/master是最新的。假设您当前正在上master,您应该可以执行以下操作:

git rebase origin/master

...这将重播所有提交不在的origin/masterorigin/master。rebase的默认操作是忽略合并提交(例如,您git pull可能已引入的合并提交),它将仅尝试将每个提交所引入的补丁应用于origin/master。(您可能需要解决一些冲突。)然后,您可以根据结果创建新分支:

git branch new-work

...然后重置masterorigin/master

# Use with care - make sure "git status" is clean and you're still on master:
git reset --hard origin/master

当使用git branchgit reset等进行这种分支操作时,我发现经常使用gitk --all或类似工具查看提交图很有用,只是检查我是否了解所有不同引用所指向的位置。

另外,您可能只是基于母版的位置(git branch new-work-including-merges)创建了一个主题分支,然后master按上述方式进行了重置。但是,由于您的主题分支将包括来自的合并,origin/master并且您尚未推送更改,因此建议您进行基准调整,以使历史记录更整洁。(此外,当您最终将主题分支合并回master时,更改将更加明显。)


8
@Olie:不,根据问题的假设以及我在答案顶部列出的假设,答案是正确的。应该在单独的新分支上的提交已经在master;rebase重写master分支,以使新的提交线性地位于顶部origin/master,然后git branch new-work创建一个new-work指向master(当前分支)尖端的分支,而无需将当前分支切换到new-work。因此,现在new-work包含所有新提交。然后复位将当前分支(静止master)移回origin/master
Mark Longair

1
@Quintesse:非常抱歉,如果您丢了工作,但是我敢肯定,这个答案对于原始提问者所描述的情况是正确的。(我只是希望对Olie的讲话予以澄清。)无论如何,以防万一有助于您找回工作,我应该说,如果您的工作是在最近几天内完成的(此问题和答案中的一项假设) ),您应该可以轻松地通过git reflog检索它。
Mark Longair

5
@Olie:也许是一种更好的解释方式:git中的分支就像指向特定提交的标签;如果您在该分支上创建它们,则它们会自动移动到新提交,或者可以通过git reset其他方式移动。该git branch new-work只是说:“创建一个分支指向该承诺,而我留在我的当前分支(这是主在这种情况下)”。因此,有没有必要有一个命令,移动的提交由主到新的分支-你只需要创建一个新的分支存在,当你重置主的新分支离开的地方主人
马克Longair

1
派对晚了一点,但@Olie只是因为在新分支上的git status并未显示master之前的提交并不意味着它们实际上不存在(假设这就是您担心的原因)。试着推新分支产地:你会看到提交在那里
费利克斯·加侬-格尼尔

2
@FélixGagnon-Grenier,不用担心“后期”-总是有人在查找旧问题,每一个澄清都会有所帮助。谢谢!:)
Olie

147

如果您的提交数量很低,并且您不在乎是否将这些提交合并为一个大型提交,则此方法效果很好,并且不像这样做那么可怕git rebase

取消暂存文件(用提交数替换1)

git reset --soft HEAD~1

创建一个新分支

git checkout -b NewBranchName

添加更改

git add -A

提交

git commit -m "Whatever"

5
要显示一个易于理解的图形,请使用git log --all --decorate --oneline --graph
EliuX

嘿@EliuX-我在这里没有相关性。你能扩大吗?
Stachu,

这对于检查您所做的操作是否得到想要的结果很有用
EliuX

4
感谢你!!这是一个非常简单的解决方案,效果很好!
克里斯·辛

90

我坚持同样的问题。我找到了最喜欢分享的最简单的解决方案。

1)使用您的更改创建新分支。

git checkout -b mybranch

2)(可选)在远程服务器上推送新的分支代码。

git push origin mybranch

3)结帐回master分支。

git checkout master

4)使用远程服务器重置主分支代码,并删除本地提交。

git reset --hard origin/master

10
那确实是最简单的方法
dhilt

4
您可以省略第2步。我认为自从给出最佳答案以来,git已经更改,并且以前不允许这样做。
塞巴斯蒂安

我认为这是最好的答案。
Macindows

1
该答案需要移至顶部。谢谢。
艾米特

27

假设branch1-是已提交更改的分支的另一种方式branch2-是理想的分支

git fetch && git checkout branch1
git log

选择您需要移动的提交ID

git fetch && git checkout branch2
git cherry-pick commit_id_first..commit_id_last
git push

现在从初始分支还原未推送的提交

git fetch && git checkout branch1
git reset --soft HEAD~1

5
Cherry-pick实际上是最好的“复制/移动单个提交”命令,尤其是。当历史成为您的重物时。
约翰诺伊豪斯

到目前为止,这是对该问题最方便的答案。谢谢您的命令!
法拉(Farah)

您可以更新未评论的提交数为1或n的最新评论吗?对于这个问题,这仍然是一个非常好的解决方案。
chAlexey

9

或者,在提交错误分支后,立即执行以下步骤:

  1. git log
  2. git diff {previous to last commit} {latest commit} > your_changes.patch
  3. git reset --hard origin/{your current branch}
  4. git checkout -b {new branch}
  5. git apply your_changes.patch

我可以想象对第一个步骤和第二个步骤有一个更简单的方法。


6

关于什么:

  1. 从当前HEAD分支。
  2. 确保您在master而不是新分支上。
  3. git reset 回到开始更改之前的最后一次提交。
  4. git pull 要重新拉动您通过重置丢弃的远程更改。

还是在尝试重新合并分支时会爆炸?


2
嗯,这基本上是上述@ Mark-Longair描述的选项B
Tim Keating

2

这是一种更简单的方法:

  1. 创建一个新分支

  2. 在新分支上执行git merge master-这会将您已提交(未推送)的更改合并到新分支

  3. 删除本地主分支git branch -D master使用-D而不是-d因为您要强制删除分支。

  4. 只需git fetch在master分支上执行一个,然后在master分支上执行一个git pull,以确保您的团队拥有最新的代码。


1

我一直在使用的一种更简单的方法(假设您要移动4次提交):

git format-patch HEAD~4

(查看您对这四个.patch文件执行最后一个命令的目录)

git reset HEAD~4 --hard

git checkout -b tmp/my-new-branch

然后:

git apply /path/to/patch.patch

您可以按照任何顺序。


0
  1. 签出您的原始资料副本

    git clone ........

  2. 从所需位置进行分支

    git checkout {position} git checkout -b {branch-name}

  3. 添加远程存储库

    git remote add shared ../{original sources location}.git

  4. 获取远程资源

    git fetch shared

  5. 结帐所需的分支

    git checkout {branch-name}

  6. 合并来源

    git merge shared/{original branch from shared repository}


0

对我来说,这是最好的方法:

  1. 检查更改并合并冲突 git fetch
  2. 创建一个新分支git branch my-changes并推送到远程
  3. 上游更改为新创建的分支 git master -u upstream-branch remotes/origin/my-changes
  4. 将提交推送到新的上游分支。
  5. 切换回上一个上游 git branch master --set-upstream-to remotes/origin/master
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.