【问题标题】:Switching branches without touching the working tree?在不接触工作树的情况下切换分支?
【发布时间】:2011-05-20 09:50:00
【问题描述】:

我目前在一个调试分支上,并且想切换到主分支,而不修改工作树(保持它在调试分支中的方式),所以我可以将一些更改提交到主分支分支。

有没有办法做到这一点?

【问题讨论】:

  • 工作树是一棵树,而不是补丁,所以如果你真的这样做了,你可能会粗暴地处理冲突的更改。 (或者确实 任何 master 中未调试的更改,如果我理解正确的话。)
  • 这并没有直接回答问题,但我发现使用工具可以达到类似的结果。具体来说,使用 IntelliJ,我可以使用“显示工作树中的差异”命令按文件夹和文件突出显示差异,然后使用“从分支获取”将所需的文件和文件夹拉入当前工作树。当我要从中挑选的分支有很多提交时,这可能比挑选樱桃更容易。

标签: git version-control branch


【解决方案1】:

您可以执行以下操作:

git checkout --detach
git reset --soft master
git checkout master

解释:

如果您在debug 分支上并且会执行git reset --soft master,您将保持工作树和索引不变,并移至master 指向的提交。问题是,debug 也将被重置为此提交。所以你在debug 上的提交是“丢失”的(嗯,不是真的,但它们不再可以直接访问),你仍然在debug 分支上。

为了防止git reset 移动debug 但仍将HEAD 设置为master 提交,您首先使用git checkout --detachHEAD 直接指向您当前的提交(参见man git-checkout 部分“分离的头”)。然后你可以在不接触debugbranch 的情况下进行重置。

现在HEAD 直接指向master 指向的提交,即它仍然是分离的。您可以简单地将git checkout master 附加到master,现在可以在master 分支上提交。

请注意git checkout(默认情况下,当没有传递路径时)只更新在“源”和“目标”提交之间更改的文件以及对工作树中文件的本地修改。由于在这种情况下两次提交是相同的,因此不会触及工作目录中的文件。

【讨论】:

  • 是的,这正是我想要的。解释也很好。
  • @Jacko 我刚刚在我的电脑上再次检查了它。唯一的区别是接受的答案是“混合”重置,我是“软”重置。如果您将--soft 排除在外,它应该与接受的答案完全相同(当然,它的第一部分)。究竟是什么不适合你?
  • 这对我来说非常有效,感觉比 symbolic-ref 的东西干净得多,这很糟糕,它必须是 3 个命令......
  • @WillemD'haeseleer 如果你经常需要这个并且输入 3 个命令对你来说太冗长了,你可以 define an alias 为它。
  • @fernacolo,感谢您的意见,我在答案中添加了一个注释。
【解决方案2】:

此答案使用低级“管道”命令。当心。如果您更喜欢“porcelain”命令,请使用this answer,它会产生相同的结果。

您可以在不更改索引或工作树的情况下将头部重置为指向 master:

git symbolic-ref HEAD refs/heads/master

您可能应该重置索引,以便有选择地应用您的工作树更改,否则您最终可能会提交 master 和 debug 分支之间的所有差异,这可能是一件坏事。

git reset

一旦你完成了你想要的提交,你就可以返回到你的调试分支:

git symbolic-ref HEAD refs/heads/debug-branch
git reset

【讨论】:

  • 这个答案帮助了我......像这样切换真的可以帮助将一个提交分成更小的部分。
  • 如果您想签出提交而不是分支,这是否也有效?
  • @CameronMartin: from man git-symbolic-refs, "符号引用是存储以ref: refs/ 开头的字符串的常规文件。例如,您的.git/HEAD 是内容为@ 的常规文件987654329@。”所以不,您可能希望git branch <temporary name> <commit> 创建一个以该提交为头的分支,然后更新您的.git/HEAD 以使用上述内容指向该提交。
【解决方案3】:

您可以存储 (git stash) 您的更改、切换分支、取消存储 (git stash pop) 您的更改、添加和提交更改。

如果您想要调试的确切状态,则只需将调试合并到主控(或将主控重置为调试)。

【讨论】:

  • 重置主机并不总是可靠的,也不安全,建议。如果其他分支与 master 有关系,这可能会使事情复杂化
  • debug 合并到master 通常不会使master 的树与debug 的树相同,除非(例如)master 没有新的发展,因为他们共同的祖先。
  • @sehe:很难说 OP 期望哪种结果,我提到了一些可供选择的选项。 @mark:是的,正确,但差不多;)(加上/减去debug的变化)
  • 在我看来,这个解决方案(连同来自 cmets 的评论)比使用符号引用更干净,就像公认的答案一样。
【解决方案4】:

这是一个原始的工作流程

 git stash
 git checkout otherbranch
 git stash apply
 git reset
 git add # interactively? just add the hunks/changes you want to commit
 git commit

然后回去

 git reset --hard # watch it here! make sure you haven't added more changes that you wanted to keep
 git checkout debug
 git stash pop

或者,您可以只在“此处”提交相关更改,然后将 /cherry-pick 推送到主分支。

【讨论】:

  • 谢谢! reset --soft 需要什么?
  • git reset --soft 不涉及索引或工作树 - 我认为您的意思只是 git reset
  • @Mark:好电话。 AAMOF 我做git reset - 只是认为--soft 是默认设置并希望明确说明。感谢您的纠正
  • @static_rtti:存储区可能包含已暂存的更改。 git reset [--mixed] 取消暂存它们,以便您可以从头开始选择要在 master 上提交的更改
【解决方案5】:

据我所知,你不能。分支切换意味着将位于该分支 HEAD 中的代码版本检出到工作副本中。

您想merge 您的分支机构。做

git checkout master
git merge devel

现在将同步分支。如果要合并更改的子集,可以指定提交或提交范围。 也看看cherry-pick 例如:

git checkout master
git cherry-pick devel

将devel中的最后一次提交合并回master。

如果您需要合并位于不同主机上的两个分支,请查看 git pull 和 git push。

【讨论】:

    猜你喜欢
    • 2020-05-31
    • 2010-10-03
    • 2014-07-10
    • 2012-11-18
    • 2012-01-24
    • 2019-12-13
    • 2010-11-19
    • 2016-07-09
    • 2013-11-11
    相关资源
    最近更新 更多