9

Есть репозиторий с ветками master и develop.

Работал с веткой develop, внес несколько изменений.

Как правильно создать новую ветку feature которая будет копией develop (с сохранением всех изменений), а develop привести к состоянию предыдущего коммита?

Nick Volynkin
  • 34,094
atom-22
  • 1,323

3 Answers3

18

Прядок действий:

git checkout -b <new-branch>

Это оставит вашу текущую ветку в текущем состоянии, создаст и сделает активной новую ветку с сохранением всех изменений. Потом можно делать коммиты:

git add <files>

И коммитить в новую ветку:

git commit

Изменения в рабочей директории — как индексированные, так и неиндексированные — пока не принадлежат ни 1 ветке. Этими действиями вы измените ветку, в которой будут сохранены изменения.

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

Это перевод ответа @knittl Move existing, uncommited work to a new branch in Git

atom-22
  • 1,323
  • Рад видеть переводчика вопросов по Git! Перевел что понял, с этой фразой действительно проблема. Кстати, в ЛС тут нельзя писать ) – Nick Volynkin Jul 24 '15 at 18:55
  • @NickVolynkin Благодарен за вашу помощь, а с ЛС я действительно "погорячился" :) – atom-22 Jul 25 '15 at 13:47
  • автор ответил: http://stackoverflow.com/questions/1394797/move-existing-uncommited-work-to-a-new-branch-in-git/1394804?noredirect=1#comment51223110_1394804 – Nick Volynkin Jul 26 '15 at 15:39
2

Как правильно создать новую ветку feature которая будет копией develop

например, так:

$ git branch feature develop

а develop привести к состоянию предыдущего коммита?

например, так («предыдущий» — в буквальном смысле, т.е. на один коммит «назад» по истории):

$ git checkout develop
$ git reset --hard HEAD^

но тут есть «подводный» камень — если эта ветка синхронизируется ещё с каким-нибудь репозиторием, то такое удаление приведёт лишь к дальнейшим проблемам.

по-моему, лучший путь: не переписывать историю существующих веток, а просто создавать новые. например, так, как в первом примере (но с «отступом» на один коммит назад от текущего состояния ветки develop):

$ git branch newdevelop develop^
  • @NickVolynkin, возможно, но вряд ли. потому что заключительная фраза вопроса с такой поправкой: develop привести к состоянию последнего коммита в develop — звучит, по-моему, ещё более загадочно. – aleksandr barakin Jul 24 '15 at 19:01
2

а develop привести к состоянию предыдущего коммита?

Насколько я понимаю, под «предыдущим» здесь понимается последний, т.е. HEAD, а не HEAD^.

Оба предлагаемых способа приводят к тому, что ветка develop остается нетронутой, а «хвост изменений» исчезает из нее, становясь новым коммитом в new_branch. Когда вы переключитесь обратно на develop, рабочая область снова будет чистой (т.е. соответстовать HEAD).

Через checkout -b

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

Итак:

  1. Индексируем всю рабочую область

    git add .
    
  2. Создаем ветку

    git checkout -b new_branch
    
  3. Делаем коммит, если хотим. Можно продолжить работу и сделать коммит позже.

    git commit -m'commit message'
    

Через stash branch

Можно сохранить изменения в stash, а потом создать из них новую ветку. Каждое сохрание в stash по своей структуре — это такой же коммит. Просто он хранится особым образом.

  1. Сохраняем в stash текущие изменения

    git stash save --all 
    
  2. Делаем новую ветку на основе только что сохраненного stash (при этом сохраненный stash остается в начале стека). Последним коммитом этой ветки будет тот, который был последним, когда создавался stash (в нашем случае это и есть последний коммит копируемой ветки).
    В результате этой команды у нас есть новая ветка, мы в нее переключились, а в рабочей области — содержимое последней записи в stash.

    git stash branch new_branch
    
  3. Теперь можно индексировать изменения и создавать коммит. Как и в прошлом случае, это можно сделать сразу или потом.

    git add .
    git commit -m'commit message'
    
Nick Volynkin
  • 34,094
  • А если в старую ветку уже сделан коммит, можно так начать новую ветку, чтобы этот коммит оказался в ней вместо старой? – Aleksandr Shemetillo Mar 16 '18 at 21:46
  • 2
    @AleksandrShemetillo начните новую ветку от этого коммита, а старую подвиньте на один назад. Как подвинуть: пункт 4.3 в этом ответе. https://ru.stackoverflow.com/a/431521/181472 – Nick Volynkin Mar 17 '18 at 03:39