GIT: зафиксировать изменения в старой / безопасной ветке, находясь в новой / грязной / ветке dev, без извлечения или потери неустановленных данных - PullRequest
11 голосов
/ 19 сентября 2010

Я создал новую ветку прежде, чем начал разрабатывать что-то экспериментальное. Я обычно забываю это (что не проблема), но теперь я сделал это заранее.
С тех пор я обновил 3 файла.

  • В 2 приведены только экспериментальные изменения, которые я НЕ хочу вносить в безопасную ветку.
  • В 1 есть только безопасные (незначительные) изменения, которые я определенно хочу зафиксировать в безопасной ветке. Я согласен с этими последними изменениями, которые будут внесены и в новую ветку (но, скорее, нет).

Возможно ли - я уверен, что это - (быстро) зафиксировать несколько неустановленных, незафиксированных изменений из моего (грязного) рабочего каталога в старую, безопасную ветку?

Единственное, о чем я могу думать, это переключение веток (без проверки), фиксация изменений в 1 файле и переключение обратно, но я не знаю, что произойдет с изменениями при переключении обратно на грязную ветку ( они все еще там или они «исчезают» из-за коммита?) ...

Я уверен, что в GIT есть что-то прекрасное для этого, но в GIT так много, что я не могу найти точно такую ​​же вещь.
(Я использовал это «руководство» для помощи , но я не уверен, что там точно такая же вещь. Если это так (и вы готовы отсканировать это), пожалуйста, дайте мне знаю, так что я знаю, в следующий раз, чтобы выглядеть сложнее.)

Спасибо! А пока я просто буду держать под рукой листок бумаги с изменениями, чтобы «зафиксировать безопасную ветвь позже».

Ответы [ 3 ]

7 голосов
/ 20 сентября 2010

Нет способа добавить коммит в альтернативную ветку с git commit .Существуют способы использования низкоуровневых «слесарных» команд для выполнения именно того, что вы описали, но интерфейс, созданный этими командами, не предназначен для интерактивного использования 1 .Конечно, есть способы делать то, что вы хотите;в зависимости от деталей ваших изменений и содержимого участвующих веток это может быть довольно просто.

Простой случай: просто используйте git checkout

При переключении веток git checkout сохранит незафиксированные изменения или откажется переключаться (если вы не используете --force, --merge или --conflict).Таким образом, до тех пор, пока ваши незафиксированные изменения касаются только тех файлов, которые одинаковы как в HEAD (текущая ветка), так и в вашей ветке назначения, git checkout оставит эти изменения в индексе и / или рабочем дереве, покапереключение веток.Если ваши неподтвержденные изменения удовлетворяют этому условию, вы можете сделать следующее:

git checkout safe-branch
git add -- files-with-safe-changes
git commit
git checkout -

Вы также можете использовать git add --patch для подготовки и фиксации только некоторых изменений в файлах.

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

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

git stash save
git merge safe-branch
git stash pop --index

Если ваши другие изменения не зависят от «безопасных изменений»тогда вам, вероятно, не стоит беспокоиться о слиянии или перебазировании.В конце концов вы объедините эти ветви вместе (например, объединяя их обе в ветку 'qa' для предварительного тестирования), но нет причин преждевременно объединять их.

Все еще легко, но немного рискованно:git checkout -m

Если первая git checkout жалуется «У вас есть локальные изменения на some‑file;не переключать ветки. », это означает, что вы внесли несоответствующие изменения в some-file и что файл отличается от подсказок« безопасной ветки »и вашей текущей ветки;вам понадобится другой подход.

Если вы уверены, что изменения будут справедливо применяться к версии some‑file, находящейся в «безопасной ветке», тогда вы можете использовать -m / --merge возможность указать git checkout , чтобы попытаться адаптировать изменения, чтобы они применялись к файлам в «безопасной ветке».Если слияние не может быть выполнено без ошибок, то в конечном итоге вы столкнетесь с конфликтом слияний, и вам может быть трудно восстановить ваши первоначальные изменения (вот почему я называю это «рискованным»).

Безопасный: git stash + git checkout -m

Поскольку вы действительно хотите переместить подмножество изменений обратно в «безопасную ветвь», возможно, лучше сосредоточиться только на этих изменениях.Один из способов - использовать git stash для временного сохранения текущих изменений, чтобы вам не приходилось перетаскивать их все обратно в «безопасную ветвь» (а затем перетаскивать некоторые / большинство из них обратно на работу.филиал).

git stash save
git checkout stash -- files-with-save-changes
git checkout -m safe-branch
git commit
git checkout -
git stash pop --index

Возможны другие варианты.Вы можете использовать git checkout -p stash -- files, чтобы выделить только некоторые изменения в этих файлах.Если в индексе нет поэтапных изменений, то вы могли бы сначала выполнить «безопасные изменения», git add -- files (снова, необязательно с -p), использовать git stash save --keep-index, переключать ветви (с объединением), а затем фиксировать (т.е. замените git checkout stash -- files на предварительно подготовленные «безопасные изменения» и git stash --keep-index).

В этой ситуации я считаю git checkout -m безопасным, потому что мы использовали git stash сохранить копию текущих изменений; если трехсторонняя попытка слияния приводит к безнадежному беспорядку, то вы можете легко отказаться от идеи поместить «безопасные изменения» в «безопасную ветвь» и вернуться к работе: переключитесь на исходную ветвь и вытолкните тайник ( git checkout -f - && git stash pop).

Опять же, если ваши другие изменения зависят от «безопасных изменений», вам потребуется слить или перебазировать. С тем же успехом вы можете сделать это перед извлечением тайника (поскольку для слияния / перебазирования вам нужен чистый индекс и рабочее дерево).

Если вы не собираетесь объединять вашу рабочую ветку с (или перебазировать ее) с «безопасной веткой» сразу, то вы, вероятно, захотите отменить «безопасные изменения» после того, как вы вытолкнули тайник («безопасный»). изменения »были сохранены в исходном хранилище, и вы, вероятно, не захотите получить коммиты, которые делают одинаковые изменения с нуля в двух разных ветках 2 ). После того, как вы открыли тайник, используйте git checkout -- files-with-safe-changes, чтобы вернуть эти файлы обратно к версиям в конце рабочей ветви.


1 Интерфейс «сантехника» предназначен для использования в скриптах. Было бы неудобно использовать их непосредственно в командной строке. Ранние версии git commit (и большинство других команд Git) были сценариями оболочки, основанными на этом интерфейсе. Они все еще могут быть написаны как сценарии оболочки сегодня, но версии C, как правило, намного быстрее. Шаги, необходимые для фиксации в альтернативной ветви:
установить альтернативный индекс на основе дерева в кончике «безопасной ветви»,
обновить индекс «безопасными» изменениями (что, если изменения не могут быть применены корректно? было бы хорошо иметь рабочее дерево, позволяющее пользователю разрешать конфликты),
записать индекс в виде объекта дерева,
создайте новый объект фиксации, который указывает на новое дерево и в качестве родителя которого используется текущий совет «safe branch»,
обновите ссылку «безопасная ветка», чтобы она указала на новый коммит.

2 Технически нет ничего плохого в фиксации ваших «безопасных изменений» в двух ветвях, но обычно хорошей идеей является убедиться, что каждое изменение происходит только из одного места.

6 голосов
/ 19 сентября 2010

Итак, ваша ситуация

x--x--x (safe)
       \
        <a,b,c> (3 private evolutions in exp branch)

И вы хотите перейти на

x--x--x--a (a committed only in safe banch)
       \
        b,c (b and c commited in exp branch)

Вы можете:

git add a
git commit -m        # in exp branch, gasp!
git stash save       # save the rest of the exp work in progress
git checkout master
git merge exp        # fast-forward merge

x--x--x--a (safe,exp)
          \
           [b,c] (stashed)

git branch -f exp HEAD~1  # reset branch exp to before 'a'
git checkout exp
git stash pop
git add -A
git commit -m "..."

x--x--x--a (a committed only in safe banch)
      \
        b,c (b and c commited in exp branch)
0 голосов
/ 19 сентября 2010

Поскольку операции ветвления в GIT такие дешевые, я бы просто использовал следующий рабочий процесс:

  • Создайте новую ветку на своей "экспериментальной" ветке
  • зафиксируйте любые необработанные файлы
  • вернуться к мастеру
  • cherrypick независимо от того, что получено от вашего "эксперимента" и новой ветви, только что созданной на шаге 1.
  • вернуться в "экспериментальную" ветку
...