Если у вас есть изменения, т. е. грязное рабочее дерево, вам нужно что-то зафиксировать. В лучшем случае у вас есть что-то, что вы хотите зафиксировать временно.
В других системах управления версиями вы можете сделать это, зафиксировав его в ветке. В Git это тоже можно сделать: вам не обязательно использовать ветку, но это может быть наиболее удобным способом работы с ней и в Git.
Вы упоминаете начальный сценарий, для которого у меня есть рабочий шаблон, который я считаю полезным:
Очень распространенный сценарий, возникающий, когда люди пишут код вместе, заключается в том, чтобы привести себя (скажем, ветку функций, над которой вы работаете) в актуальное состояние.
Допустим, вы работаете над feature-X
, который в итоге будет помещен в dev
(ветвь разработки). Другие разработчики работали над функциями Y и Z, и одна из них завершена, а dev
теперь обновлена, поэтому вы запускаете:
$ git fetch
и видим, что ваш dev
теперь позади origin/dev
. То есть теперь у вас есть:
...--C--D--H <-- master
\
\ I--J <-- origin/dev
\ /
E--F--G <-- dev, feature-X (HEAD)
в вашем репозитории. У вас также есть некоторые вещи в вашем рабочем дереве, которые отличаются от файлов в коммите G
. (Возможно, у вас еще нет ветки с именем feature-X
, и вместо этого HEAD
присоединена к dev
. В этом случае вы можете просто создать ее сейчас с git checkout -b feature-X
, и теперь вы соответствуете картинке.)
Что нужно сделать на этом этапе, так это зафиксировать материал, над которым вы работаете в любом случае. Это делает один новый коммит K
:
...--C--D--H <-- master
\
\ I--J <-- origin/dev
\ /
E--F--G <-- dev
\
K feature-X (HEAD)
Теперь вы можете перемотать свои собственные файлы с dev
на origin/dev
. Основной метод команды:
$ git checkout dev # safe, since your work is committed
$ git merge --ff-only origin/dev # or `git pull` if you really insist
Теперь рисунок выглядит так:
...--C--D--H <-- master
\
\
\
E--F--G--I--J <-- dev (HEAD), origin/dev
\
K <-- feature-X (HEAD)
Здесь большинство людей просто запускают git checkout feature-X; git rebase dev
, и это нормально, и вы можете свободно использовать этот метод. (Я часто так делаю. Подумайте о том, чтобы сделать это с последующим приемом git reset HEAD^
, описанным ниже.) Но иногда я просто переименовываю feature-X
в feature-X.0
, а затем создаю новый< /em> feature-X
с git checkout -b feature-X
:
...--C--D--H <-- master
\
\
\
E--F--G--I--J <-- dev, origin/dev, feature-X (HEAD)
\
K <-- feature-X.0
Теперь я готов снова начать работу над feature-X
, и на данный момент я просто выбираю все коммиты feature-X.0
:
$ git cherry-pick dev..feature-X.0
который создает коммит K'
, который является копией K
:
...--C--D--H <-- master
\
\ K' <-- feature-X (HEAD)
\ /
E--F--G--I--J <-- dev, origin/dev
\
K <-- feature-X.0
Это работает, даже если на feature-X.0
есть несколько коммитов:
...--C--D--H <-- master
\
\ K'-L' <-- feature-X (HEAD)
\ /
E--F--G--I--J <-- dev, origin/dev
\
K--L <-- feature-X.0
Если последняя фиксация этого нового feature-X
(L'
в этой версии, K'
в той, в которой была только одна фиксация) действительно, серьезно еще не готова к фиксации, на данный момент я просто используйте git reset HEAD^
(вы можете написать это HEAD~
, если это проще, как, по-видимому, в Windows), чтобы переместить имя ветки на один шаг назад. Это удаляет самый последний коммит из текущей ветки, давая:
...--C--D--H <-- master
\
\ K' <-- feature-X (HEAD)
\ /
E--F--G--I--J <-- dev, origin/dev
\
K--L <-- feature-X.0
и оставляет рабочее дерево "грязным" именно таким, каким оно было до того, как я начал весь этот процесс. (В общем, частичная фиксация — это нормально, так как я буду использовать git rebase -i
позже, чтобы очистить все, когда feature-X
будет в основном готов.)
Если по какой-то причине мне нужно повторить процесс, я переименовываю текущий незавершенный feature-X
в feature-X.1
, или feature-X.2
, или как-то еще. Я выращиваю небольшую коллекцию feature-X
-ов и время от времени выхожу в сад с ветками и обрезаю самые сорные. Самый последний и самый лучший по-прежнему называется feature-X
, но все мои предыдущие работы доступны по мере необходимости, пока я их не отсею. Это лучше, чем либо перебазировать или заначка, потому что, если код сложный и я что-то упускаю, у меня остается старая версия, под узнаваемым именем, а не какой-то непонятный хеш ID в рефлоге, и не заначка, неотличимая от десятка других заначек.
person
torek
schedule
29.09.2018