我们使用git来管理我们应用程序的代码库,并且遇到了我尚未遇到的情况,但我认为这种情况很常见。
我们希望暂时删除某个功能,然后在将来的某个时候将其重新添加。我试图想象支持这个的分支结构,或者我们应该做一些简单的事情,比如从代码中删除该功能,并且当准备好重新添加它时,从提交历史中重新创建它。
在处理这种情况方面,有人能指出我正确的方向吗?
答案 0 :(得分:8)
您可以暂时删除Git仓库历史记录之前的功能的一种方法是进行删除功能的提交。然后,当您想要重新添加该功能时,只需将revert the commit取出即可。这将执行反向补丁,这意味着它将反向应用更改,这将有效地重新添加功能:
git revert <sha of commit that removed the feature>
如果您希望稍后通过与同时更改代码保持同步来轻松地重新添加该功能,则可以在删除后立即创建单独的功能分支,然后只需像任何其他功能分支一样处理该分支,并通过频繁地将其重新定位到master
(或develop
分支,如果这是您想要的方式)来保持同步,并随着时间的推移解决冲突
所以基本上,你会想要做这样的事情(如果你使用的是GitHub Flow或Git Flow分支策略,那么两者都使用功能分支的概念最终被合并到一个开发的主线。为简单起见,我将在这个例子中使用GitHub Flow:
# On master branch
git commit -m "Remove feature X" # Creates commit 1234567...
# Now make feature branch
git checkout -b saved-feature
# Immediately put the feature back in the feature branch
git revert 1234567
# When you want to sync branch with master, just use rebase.
# Rebase allows you to sync frequently, since it doesn't
# leave behind a bunch of merge commits.
#
# From the feature branch:
git rebase master # Resolve any conflicts as needed.
# N commits later, you decide it's time to merge the feature
# back in. You can use fast-forward or non-fast-forward merge,
# it's up to you.
#
# Using fast-forward merge with master checked out (assuming
# feature branch was just rebased onto master):
git merge saved-feature
# Or forcing a merge commit, if that's what you want:
git merge --no-ff saved-feature
假设您已经saved-feature
经常与master
(或develop
同步,如果这是您使用的)同步,解决冲突,您应该没有问题合并功能重新进入。
供参考的文件:
答案 1 :(得分:2)
这是一个应该有效的策略。听起来你的工作非常适合你的项目,所以这就是我要做的。首先选择你的起点,对我来说通常是dev
分支(假设还有一个master branch
)。拆除将从项目中删除的功能的新分支
git checkout -b dev_feature_removed
同时旋转将在项目中维护该功能的分支。
git checkout -b dev_feature_sustained
现在进行编码和测试,确保在dev_feature_removed
中正确并完全删除此功能,并且一旦确定这是合并分支回生产的情况。在我的情况下,开发进行进一步的测试,然后进入主人的生活。
与此同时,您可以将您的其他分支dev_feature_sustained
保留在您的回购中。您可以将dev合并到此分支以保持同步,并将其添加到已删除的功能(错误修复或新的铃声和口哨),当它返回到生活时通过将其合并回dev(在我的情况下可能是您的主人) )。
此功能的返回可能会导致合并冲突,具体取决于您的功能的紧密耦合程度。因为你的回购之前,听起来你无论如何都会产生冲突,因为合并策略只能做很多事情。但是,由于您将拥有两个完整的提交树,一个具有该功能,另一个没有,您将了解功能重新连接到项目的每个点的存在。因此,您将拥有将其放回项目中所需的一切。这就是我在我的案例中起草的内容。祝你好运,伙计。
答案 2 :(得分:2)
以下是在John Galt's answer中显示策略的具体示例:
$ git log --graph --decorate --oneline
* d1d201b (HEAD, restore-b) Merge branch 'prod' into restore-b
|\
| * 18d759f (prod) add feature e in prod
* | 191037e Merge branch 'prod' into restore-b
|\ \
| |/
| * e0de1be add feature d in production
* | a122936 Revert "remove feature b in production"
|/
* d3e2c42 remove feature b in production
* 5369ecf existing three features
基本上,restore-b
始终包含prod
中的所有内容以及功能的恢复(commit a122936
)。当您在prod
上进行新提交时,它们会合并到restore-b
中,这样无论何时您准备好恢复该功能,这都是一个简单的快速合并。
更简单的方法是避免创建a112936
提交和restore-b
分支,直到您准备好恢复该功能的时间点为止。创建和保持最新restore-b
分支的优势在于,与其他更改的任何冲突都会及时解决(希望由编写冲突代码的开发人员在编写之后不久) 。这使得该功能保持“新鲜”和“在甲板上”,随时可以包含在生产版本中,无需额外的开发工作。
答案 3 :(得分:0)
我会在代码本身解决这个问题。添加一个功能映射(基本上是每个功能的布尔标志),然后根据需要启用/禁用功能,而无需实际从存储库中删除代码/逻辑。
配置文件中的一些内容很简单:
<?php
$features = array(
'news' => true,
'events' => true,
'shop' => false
);
然后在相应的控制器中:
<?php
class ShopController extends AbstractController {
public function __construct() {
// $features array would be passed in somehow;
// maybe via a dependency injection container
if (!$features['shop']) {
// feature is disabled, so just send 404 page for now
throw new ResourceNotFoundException();
}
}
}
注意:上面是半伪代码。