Временно удалить функцию из ветки Git

Мы используем git для управления нашим репозиторием кода приложения и имеем ситуацию, с которой мне еще предстоит столкнуться, но я полагаю, что это очень часто.

Мы хотели бы временно удалить функцию, а затем добавить ее обратно в какой-то момент в будущем. Я пытаюсь представить структуру ветвления, которая поддерживала бы это, или если мы должны сделать что-то столь же простое, как удалить эту функцию из кода, и когда она будет готова к ее повторной добавке, заново создайте ее из истории фиксации.

Может ли кто-нибудь указать мне в правильном направлении с точки зрения обработки этой ситуации?

Ответ 1

Один из способов временно удалить вашу функцию, которая предшествует вашей истории репо Git, - это сделать фиксацию, которая удаляет эту функцию. Затем, когда вы захотите добавить эту функцию, просто верните фиксацию, которая ее вытащила. Это сделает обратный патч, что означает, что он применит изменения в обратном порядке, что эффективно добавит эту функцию:

git revert <sha of commit that removed the feature>

Если вы хотите, чтобы вы могли легко добавить функцию позже, сохраняя при этом синхронизацию с изменениями кода, вы можете создать отдельную ветвь функции сразу после ее удаления, а затем просто обрабатывайте эту ветвь, как любую другую ветвь функции, и держите ее в синхронизации, часто перезаряжая ее с помощью master (или ветки develop, если это так, как вы хотите это сделать), разрешая конфликты по ходу.

Итак, в принципе, вы хотели бы сделать что-то вроде этого (неважно, если вы используете поток GitHub или 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 time to merge the feature
# back in.  You can use fast-forward or non-fast-forward merge,
# it 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 what you want:
git merge --no-ff saved-feature

Предполагая, что вы часто синхронизировали saved-feature с master (или develop, если это то, что вы используете), разрешая конфликты, когда вы идете, у вас не должно возникнуть проблем с объединением функции.

Документация для справки:

Ответ 2

Это стратегия, которая должна работать. Похоже, ваша работа очень испекла в ваш проект, так что вот что я буду делать. Сначала выберите начальную точку, для меня обычно dev branch (предполагается, что есть также master branch). Выделите новую ветку, которая будет удалена из вашего проекта

git checkout -b dev_feature_removed

Также в то же время вращение ветки, которая будет той функцией, поддерживаемой в проекте.

git checkout -b dev_feature_sustained

Теперь выполните кодирование и тестирование, чтобы убедиться, что эта функция правильно и полностью удалена в dev_feature_removed, и как только вы убедитесь, что это слияние, которое возвращается в производство. В моем случае dev для дальнейшего тестирования, а затем в мастер, чтобы жить вживую.

Между тем вы можете сохранить свою другую ветку dev_feature_sustained также в своем репо. Вы можете объединить dev в эту ветку, чтобы синхронизировать ее, а также добавить к вашей удаленной функции (исправления ошибок или новые колокола и свистки) в тот день, когда она возвращается для жизни, объединив ее обратно в dev (в моем случае, вероятно,).

Это возвращение функции может вызвать конфликты слияния в зависимости от того, насколько тесно связана ваша функция. Так как ваш предшествует репо, похоже, что вы будете генерировать конфликт независимо от того, потому что стратегии слияния могут делать только так. Однако, поскольку у вас будет два полных дерева коммита, один с функцией и один без, вы узнаете о существовании каждой точки, в которой ваша функция будет повторно подключаться к вашему проекту. Таким образом, у вас будет все, что вам нужно, чтобы поместить его обратно в свой проект. Это то, что я хотел бы сделать в моем случае. Удачи, человек.

Ответ 3

Вот конкретный пример, показывающий стратегию в Ответ Джона Галта:

$ 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 commit и restore-b до момента, когда вы будете готовы воскресить эту функцию. Преимущество создания и поддержания последней ветки restore-b заключается в том, что любые конфликты с другими изменениями решаются один за другим своевременно (надеюсь, разработчик, который написал противоречивый код, вскоре после его написания). Это сохраняет функции "свежие" и "на палубе", готовые к включению в производственный выпуск без дополнительных разработок.

Ответ 4

Id решает это в самом коде. Добавьте карту функций (которая в основном является логическими флагами для каждой функции), а затем просто включите/отключите функции по мере необходимости, без фактического копирования кода/логики из вашего репозитория.

Что-то в файле конфигурации так же просто, как:

<?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();
        }
    }
}

Примечание: выше - полу-псевдокод.