Какой лучший способ сделать «временный» коммит в git? - PullRequest
19 голосов
/ 17 октября 2010

Скажем, у меня есть проект с двумя ветвями master и dev. У меня есть куча коммитов на dev для специального события, которые после тестирования объединяются в master. Затем, после того, как событие закончится, я хочу удалить код, специфичный для события. Однако сброс git не будет выполняться, поскольку после добавления кода события были сделаны другие коммиты.

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

У кого-нибудь есть лучшее решение для временного кода в проекте?

Edit: Для ясности, изменения должны быть зафиксированы, отправлены, незафиксированы, отправлены.

Ответы [ 7 ]

18 голосов
/ 17 октября 2010

Возьмите мастера и создайте ветку: git checkout -b special-event, внесите / примените ваши изменения.Как только событие закончится, просто переключитесь обратно на master и отмените / удалите ветвь.

Чтобы продолжить вносить изменения, внесите их в master и объедините их в специальную ветку по мере продвижения.git checkout master ... вносить изменения ... git checkout special-event; git merge master.

В качестве альтернативы внесите все изменения, связанные со специальными событиями, в один коммит, затем используйте git revert, когда вы хотите их развернуть, и укажите толькоэтот коммит.

2 голосов
/ 07 сентября 2012

«Временный код»? В git мы используем для этого ветки. Коммиты очень легки в git, а ветки, являющиеся просто именами (или ссылками) для коммитов с небольшой долей логики, являются сверхлегкими по сравнению с другими системами.

Небольшая логика в том, что ссылка автоматически обновляется до последнего коммита. Это в значительной степени все, что такое филиал. Это означает, что создание и уничтожение веток в git - это быстро, просто и даже безопасно, поскольку на самом деле ничего не создается и не удаляется. После удаления вы по-прежнему можете ссылаться на заголовок ветки по идентификатору коммита (да, он остается там до тех пор, пока не будет собран мусор, и даже это происходит, только если на него нет другой ссылки).

Почти каждая команда в git принимает в качестве параметров ссылки на коммит. Это верно и для git merge. Вы не объединяете ветви, вы объединяете коммиты. Да, вы набираете 'git merge', но опять же, ветвь - это просто имя для коммита. Не более того. А поскольку все, что вам нужно, это группировать коммиты для события вместе, просто дайте им имя.

Так что правильно сделать, это создать ветку для события. Или, возможно, два: 'event-master' и 'event-dev'. Теперь вы разрабатываете код для события в 'event-dev'. Если вы столкнетесь с ошибкой, которую необходимо исправить в основном коде, спрячьте и переключитесь на обычную ветку 'dev', кодируйте исправление и фиксируйте. Вернитесь к 'event-dev', объединитесь с 'dev' и извлеките тайник. Продолжайте разрабатывать, когда закончите, зафиксируйте и протестируйте. Если все в порядке, объедините «event-dev» с «event-master». Это будет содержать также исправление. Обратите внимание, что исправление еще не внесено в «master».

Если вам нужно объединить исправление с «master», вы просто делаете это обычным способом, поскольку исправление находится в «dev».

В основном в этой настройке вы можете:

  • разработать основной код как обычно: вы берете на себя «dev», тестируете и объединяетесь с «master»;

  • разработать код, специфичный для события, аналогичным образом: вы фиксируете 'event-dev', тестируете и объединяетесь в 'event-master'; это просто тот же рабочий процесс;

  • смешать два рабочих процесса; передайте и переключите ветку или используйте git stash;

  • сливать ветки (почти) свободно; вы можете объединить «master» в «event-dev», если master как-то обновлен и вам нужны изменения для события; Вы можете объединить «dev» в «event-dev», если вам крайне необходимы изменения для события и вы не можете ждать обычного цикла тестирования, который переводит их в «master». git сделает это, если слияния будут чистыми, то есть если вы не изменили один и тот же кусок кода двумя разными способами в ветвях с двумя -dev (это, конечно, особый случай, который необходимо обработать);

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

Наконец, я должен отметить, что этот рабочий процесс настолько естественен в git. На самом деле, развитие в «dev» и внесение изменений в «master», вообще говоря, даже не самое лучшее. Обычно для каждой разрабатываемой вами функции или модуля создается ветка dev, и эти ветки объединяются в dev.

Я думаю, что правильное мышление при использовании git таково: «что я чувствую, когда пишу код сегодня? Функция X. Хорошо, давайте создадим ветку 'feature-x' и начнем хакерство". Это ваше событие ничем не отличается.

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

Время переписывать историю.Насколько это будет сложно, зависит от характера изменений.Например, если все изменения принадлежат одному каталогу, все может быть проще.

Вот что я хотел бы сделать (не зная лучше):

  • изучить историю сgit log;

  • найдите коммит, который находится прямо перед первым конкретным изменением события, обратите внимание на его commit-id: это коммит 'day-0';

  • создайте ветку с именем 'newdev', указывающую на этот коммит.Сделайте это в чистом дереве, то есть перед тем как сделать следующее: git checkout-b newdev;

  • создать 'event-dev': git checkout -b event-dev;

  • теперь у вас есть две ветвиоба указывают на коммит 'day-0';

  • теперь снова просматриваем историю (git log dev), вам нужно следить за коммитом по коммиту;

  • Я предполагаю, что каждый коммит, следующий за 'day-0', является либо коммитом, который принадлежит основному коду, либо тем, который относится только к событию.Что вам нужно сделать, так это выбрать их в правой ветке: «newdev», если это основной код, «event-dev», если это код события;делайте это один раз, в правильном порядке (от «день-0» до сегодняшнего дня);

  • если вам очень повезет, ни один коммит, который заканчивается в «newdev», не зависиткоммиты в 'event-dev' и наоборот;ты вроде готов;вы можете переименовать (сохранить их) текущий мастер и dev в master-old и dev-old, затем переименовать newdev в dev, создать master из dev, event-master из event-dev, и все готово;

  • если вам повезет меньше, иногда вам придется сливать 'newdev' в 'event-dev', потому что некоторые коммиты зависят от изменений, внесенных в основной код,что хорошо, хотя;если вы чувствуете смелость здесь, пришло время прочитать о git rebase;но перебазировать не нужно, если вам не нужно;

  • или (что еще хуже) некоторые коммиты в 'newdev' зависят от изменений в 'event-dev' ... упс, этот специфичный для событиякод оказывается не столь специфичным для события, если это нужно основной ветви.Требуется некоторое слияние;

  • или (плохо) один коммит содержит оба вида изменений: разделяй и властвуй (нужно отделить изменения и применить их к правой ветке), что означает, что выделим коммит на две части:

  • или что-то еще, что я не могу себе представить сейчас, так как у меня недостаточно сведений о вашем дереве.

Это может быть ветер или кошмар.Заранее проверяйте каждый коммит (git show, вы можете посмотреть на него как на патч), решите, что делать (в конечном итоге не выбирайте вишню, просто редактирование файлов может быть проще), если не уверены - угадайте что - создайте ветку, поработайте там, посмотрите, что произойдет, объедините его, если вы довольны, оставьте его и попробуйте снова.

Я пока не упомянул об этом, но, конечно, вы можете сделать копию всего дерева, gitфайлы включены, и работать с копией, чтобы быть на 100% безопасным.

Сделать это с самого начала довольно легко.Исправляя это сейчас, хорошо, удачи.:)

1 голос
/ 10 января 2012

Сверните свои коммиты, следуя моему непатентованному методу:

# 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 (т.е. это трудно понять).

Теперь ваш коммит один.Теперь вы можете использовать возврат или сделать свой путь к ветке без него.

1 голос
/ 17 октября 2010

git checkout -b event

... внести изменения в конкретное событие ...

git commit -am "specific event change"

... внести другое конкретное изменение в событие ...

git commit -am "another specific event change"

На этом этапе ветвь master все еще не повреждена, а изменения, относящиеся к событию, происходят в ветке event . Если в основную ветку внесены изменения, которые также необходимы в ветке event , используйте rebase ...

git rebase master

В другом ответе предлагается объединить master в событие , но rebase обычно является лучшим подходом. A rebase снимает коммиты, сделанные в ветке темы, вытягивает обновленный master вперед и затем применяет изменения ветки темы сверху ... как будто изменения ветки темы были до самой последней версии мастера.

В вашем сценарии, когда событие закончится, просто удалите ветку event .

0 голосов
/ 06 января 2017

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

0 голосов
/ 18 октября 2010

git revert

Он удалит любой коммит или диапазон коммитов, которые вам нужно отменить. Это также безопасно подтолкнуть к публичному репо.

0 голосов
/ 17 октября 2010

Я верю заначка делает то, что вы хотите.

...