25

假设我有一个包含两个分支 master 和 dev 的项目。我在 dev 上为一个特殊事件提交了一堆提交,这些提交一旦经过测试就会合并到 master 中。然后在事件结束后,我想删除事件特定代码。但是 git reset 不会做,因为自从添加事件代码以来已经进行了其他提交。

目前,我使用 git checkout 来签出事件合并之前的文件,然后使用 git diff 重新添加自提交事件以来所做的更改。这对我来说似乎是一个非常混乱的方法。

有没有人有更好的解决方案来在项目中使用临时代码?

编辑:要明确更改需要提交、推送、未提交、推送。

4

7 回答 7

21

获取 master 并创建一个分支:git checkout -b special-event,进行/应用您的更改。事件结束后,只需切换回 master 并放弃/删除分支。

为了继续进行更改,请在 master 上进行更改,并随时将它们合并到特殊分支中。git checkout master……做出改变git checkout special-event; git merge master……

或者,在一次提交中进行所有与特殊事件相关的更改,然后git revert在您想要推出它们时使用并仅指定该提交。

于 2010-10-17T13:58:37.807 回答
4

“临时代码”?在 git 中,我们为此使用分支。git 中的提交是非常轻量级的,与其他系统相比,分支只是提交的名称(或引用),带有一点点逻辑,是超级轻量级​​的。

一点点逻辑就是引用会自动更新到最后一次提交。这几乎就是分支的全部内容。这意味着在 git 中创建和销毁分支是快速、简单甚至安全的,因为没有真正创建或删除任何内容。删除后,您仍然可以通过 commit-id 引用分支头(是的,它仍然存在,直到它被垃圾收集,即使只有在没有其他引用时才会发生这种情况)。

几乎 git 中的每个命令都将提交的引用作为参数。git merge 也是如此。您不是在合并分支,而是在合并提交。是的,你输入 'git merge',但同样,分支只是提交的名称。仅此而已。而且由于您只需要将事件的提交分组在一起,只需给它们起一个名字。

所以正确的做法是为事件创建一个分支。或者可能是两个:“event-master”和“event-dev”。现在,您在“event-dev”中为事件开发代码。如果您遇到需要在主代码中修复的错误,请隐藏并切换到您的正常“开发”分支,将修复代码写入并提交。切换回“event-dev”,从“dev”合并,然后弹出存储。继续开发,一旦完成,提交和测试。如果没问题,将 'event-dev' 合并到 'event-master' 中。这也将包含修复。请注意,修复尚未在“主”中。

如果您需要将修复合并到“master”中,您只需按照通常的方式进行操作,因为修复位于“dev”中。

基本上在此设置中,您可以:

  • 像往常一样开发主要代码:你提交到'dev',测试并合并到'master';

  • 以类似的方式开发特定于事件的代码:您提交到“event-dev”,测试并合并到“event-master”;这只是相同的工作流程;

  • 混合两种工作流程;提交和切换分支,或者使用 git stash;

  • (几乎)自由地合并分支;如果 master 以某种方式更新并且您需要事件的更改,您可以将“master”合并到“event-dev”中;如果您迫切需要事件的更改并且不能等待将它们推入“主”的通常测试周期,您可以将“开发”合并到“事件开发”中。只要合并是干净的,git就会这样做,也就是说,除非您在两个 -dev 分支中以两种不同的方式更改了同一段代码(这当然是需要处理的特殊情况);

如果您需要额外的灵活性,请创建更多分支。为了获得超级灵活性,您可以将单个提交挑选到分支中,但总的来说我建议不要这样做(只有在您真正知道自己在做什么时才这样做)。

最后,我应该指出,这个工作流程在 git 中是如此自然。实际上,一般来说,在“dev”中开发并在“master”中拉动变化甚至不是最好的。通常为您正在开发的每个功能或模块创建一个 dev 分支,并将这些分支合并到“dev”中。

我认为使用 git 时正确的心态是:“我今天想写什么代码?功能 X。好,让我们创建分支 'feature-x' 并开始 hacking。”。你的那个事件也不例外。

现在,我知道我要告诉你的是你从一开始就应该如何做事,而现在这并没有多大帮助。您需要修复您的树,因为 - 看起来 - 您将事件的更改与正常的更改混合到您的“开发”分支中。因此,您的问题是如何正确创建仅包含事件更改的“event-dev”,并同时将它们从“dev”中删除。

是时候改写历史了。这将有多难,这取决于变化的性质。例如,如果所有更改都属于一个目录,事情就会变得更容易。

这是我会做的(不知道更好):

  • 用 git log 检查历史;

  • 找到第一个特定事件更改之前的提交,注意其提交 ID:这是“day-0”提交;

  • 创建一个指向该提交的名为“newdev”的分支。在干净的树中执行此操作,即在执行此操作之前提交: git checkout <commit-id> -b newdev;

  • 创建“事件开发”: git checkout -b 事件开发;

  • 你现在有两个分支都指向“day-0”提交;

  • 现在再次查看历史记录(git log dev),您需要逐个提交跟踪它;

  • 我假设“day-0”之后的每个提交要么是属于主代码的提交,要么是仅属于事件的提交。你需要做的是在正确的分支中挑选它们,如果是主代码,则为“newdev”,如果是事件代码,则为“event-dev”;一次做一个,以正确的顺序(从'day-0'到今天);

  • 如果你很幸运,任何以“newdev”结尾的提交都不会依赖于“event-dev”中的提交,反之亦然;你已经完成了;您可能希望将当前的 master 和 dev 重命名(保留它们)为 master-old 和 dev-old,然后将 newdev 重命名为 dev,从 dev 创建 master,从 event-dev 创建 event-master,然后您就设置好了;

  • 如果你不那么幸运,有时你必须将“newdev”合并到“event-dev”中,因为一些提交取决于主代码中所做的更改,这很好,但是;如果您在这里感到大胆,是时候阅读有关 git rebase 的信息了;但除非你必须这样做,否则不要变基;

  • 或者(更糟)'newdev' 中的某些提交取决于 'event-dev' 中的更改......哎呀,如果主分支需要它,那么特定于事件的代码结果不是那么特定于事件的。需要一些合并;

  • 或(坏的)一个提交包含两种更改:分而治之(您需要分离更改并将它们应用到正确的分支),这意味着您将提交分成两部分;

  • 或者我现在无法想象的其他事情,因为我没有关于你的树的足够详细信息。

这可能是微风或噩梦。事先检查每个提交(git show,您可以将其视为一个补丁),决定做什么(最终不要挑选,只是编辑文件可能更容易),如果不确定 - 猜猜 - 创建一个分支,在那里工作,看看会发生什么,如果满意就合并它,否则放弃它,然后再试一次。

到目前为止我还没有提到它,但当然你可以制作整个树的副本,包括 git 文件,并且在副本上工作是 100% 安全的。

从一开始就做好是相当容易的。现在修复它,好吧,祝你好运。:)

于 2012-09-07T12:16:44.810 回答
4

按照我的非专利方法汇总您的提交:

# work on a new branch
git checkout -b event-36
git commit -a -m "all broken dammit"
git commit -a -m "fixed that damn code"
git commit -a -m "almost ready, going to eat lunch"
git commit -a -m "It's done!"

# other people might be working on master in the meantime, so
git checkout master
git checkout -b erasemeImmediately
git merge event-36
git reset --soft master # THE KEY TO THE WHOLE THING: SOFT RESET!
git commit -a -m "Event 36, all code in one commit"

git checkout master
git merge erasemeImmediately

您可以使用 来做到这一点reflog,但是您需要最近的 CS 学位(即,这很难理解)。

现在你的提交是一个单一的。现在,您可以使用 revert 或在没有它的情况下选择进入分支的方式。

于 2012-01-09T20:46:57.927 回答
2

我相信stash可以满足您的要求。

于 2010-10-17T13:58:05.993 回答
1

git checkout -b event

...进行特定事件更改...

git commit -am "specific event change"

...进行另一个特定的事件更改...

git commit -am "another specific event change"

此时,分支仍然完好无损,事件特定的更改在事件分支上。如果对事件分支中也需要的主分支进行了更改,请使用rebase ...

git rebase master

另一个答案建议将master合并到eventrebase通常是更好的方法。rebase会剥离在主题分支上所做的提交,将更新后的 master 向前拉,然后在顶部重新应用主题分支更改……就好像主题分支更改是对 master 的最新版本进行的一样。

在您的场景中,当事件结束时,只需删除事件分支。

于 2010-10-17T14:47:01.840 回答
0

git 还原

它将删除您需要撤消的任何提交或提交范围。推送到公共回购也是安全的。

于 2010-10-17T23:04:05.430 回答
0

根据我的经验,一些特殊事件会反复出现。因此,这里要考虑的替代解决方案是创建一个配置选项以启用处理特殊事件,以便可以在需要时打开和关闭它。

于 2017-01-06T04:54:29.747 回答