Как переключиться на новую ветку в той же самой ветке, не сохраняя коммиты с предыдущего пу sh? - PullRequest
0 голосов
/ 10 февраля 2020

Я клонировал репо и оформить заказ на ветке featureA. Я работаю над веткой featureA и pu sh двумя коммитами.

Затем я переключаюсь на featureB и хочу сделать sh два новых коммита, но коммиты в featureA являются частью featureB. Как мне переключиться на новую ветку featureB и запустить "afre sh", которая была в состоянии до того, как я нажал два коммита?

Ответы [ 3 ]

1 голос
/ 10 февраля 2020

Если вы слили свои коммиты из филиала featureA в master, вам придется отменить изменения с master и оформить заказ в новом филиале featureB. Я предполагаю, что вы находитесь в вашей основной ветке в вашем регионе.

1. git revert <commit ID> -m <Parent number>
2. git push origin master
3. git checkout -b featureB
1 голос
/ 10 февраля 2020

Затем я переключаюсь на featureB и хочу сделать два новых коммита sh, но коммиты в featureA являются частью featureB. Как мне переключиться на новую ветку featureB и запустить "afre sh", который был в состоянии до того, как я нажал два коммита?

, если бы вы просто переключили на featureB, коммитов в featureA там не было бы. Однако, что вы, вероятно, сделали, так это то, что вы разветвляли featureB от featureA, и в этом случае также будут коммиты. Вам нужно будет перейти от мастера вместо этого. В этом случае featureB не будет знать о функции A.

Переключение ветвей выполняется с помощью:

git checkout featureB

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

git checkout -b featureB

Итак, сначала переключитесь на master, а затем ответвьте FeatureB оттуда:

git checkout master
git checkout -b featureB
0 голосов
/ 10 февраля 2020

TL; DR

Вы хотите git checkout -b featureB master или подобное.

Long

Одна из многих вещей, которые нужно узнать о Git, заключается в том, что Git не совсем о ветках . Git действительно о коммитах . Ветви - или, точнее, ветви names - это всего лишь метод, которым вы, и Git, находите , фиксируете.

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

Я клонировал репо ...

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

Когда вы делаете это git clone, в самом начале вы не получить любые веток других Git. Но они вам не нужны, потому что Git не о ветвях. Вам просто нужно имен , чтобы вы могли найти коммиты. Таким образом, ваши Git берут свои имена ветвей и сохраняют их в своем хранилище как ваши имена для удаленного слежения , такие как origin/master и origin/develop. То есть ваши Git запоминают их имена ветвей, как ваши имена для удаленного слежения.

Последний шаг процесса git clone заключается в том, что ваш Git создает в вашем хранилище одно имя ветки. Это имя одной ветви должно указывать на один из коммитов , полученных вами от их Git. Какой из этих коммитов должен использовать ваш Git? Вероятно, есть сотни или тысячи коммитов; как ваш Git выберет правильный один? Вы можете сказать это, но обычно по умолчанию: Используйте имя origin/master, которое мы получили из другого Git репозитория в origin, чтобы выбрать коммит; заставить мое новое имя ветки master идентифицировать тот же самый коммит.

Итак, если у них есть серия коммитов, заканчивающаяся на некотором га sh ID H, мы можем нарисовать это так:

... <-F <-G <-H   <-- master, origin/master

Последний из их master коммитов это ha sh H. (На самом деле ha sh - это какая-то большая уродливая строка букв и цифр - мы просто используем H для краткости.) Этот коммит хранит внутри него идентификатор ha sh некоторого другого, более раннего коммита, который мы ' позвоню G. Коммит G хранит в нем идентификатор ha sh некоторого другого более раннего коммита, который мы назовем F.

Когда вы запускаете git log, Git начинается с чтения имени master найти га sh H. Затем он показывает, что вы совершаете H. Затем он использует commit H, чтобы найти ha sh G, и показывает, что вы делаете commit G. Он использует это, чтобы найти F, и показывает вам F. Это повторяется вплоть до самого первого коммита . Этот первый коммит не больше не указывает назад, потому что не может, и вот как Git знает, как его остановить.

... и извлечение для перехода featureA.

Здесь есть две возможности: featureA существовал на origin ранее или не существовал. У вашего собственного Git еще нет featureA - у него есть master - поэтому, если вы запустите:

git checkout featureA

ваш собственный Git обычно просто скажет I не имеет featureA. Но вместо этого ваш Git проверит ваши origin/* имена, чтобы узнать, есть ли у вас origin/featureA. Если это так, ваш Git найдет коммит, который назван вашим origin/featureA, и создаст свой собственный новый featureA, указывая на этот коммит.

Если у вас нет либо origin/featureA, то вы должны указать Git создать featureA сейчас, используя либо git branch, либо git checkout -b. Вы можете сказать своему Git: Создать новое имя featureA, указывая на тот же коммит, на который указывает мое текущее имя ветви master. Это дает вам:

...--F--G--H  <-- master, featureA, origin/master

Теперь, когда у вас есть два имени ветви (плюс все имена удаленного отслеживания origin/*), нам нужно каким-то образом запомнить какое имя ветви ваше Git использует . Чтобы сделать это, мы прикрепим специальное имя HEAD в верхнем регистре, как это, к одному из двух имен ветвей.

Обратите внимание, что оба имени ветви в настоящее время оба указывают на одно и то же commit ha sh ID (H в этом примере)! Это прекрасно. Это просто означает, что обе ветви заканчиваются коммитом H.

Я работаю над веткой featureA и pu sh двумя коммитами.

Предположительно, что вы имеете в виду здесь вы создали два новых коммита, а затем использовали git push, чтобы получить другой Git репозиторий, в origin, чтобы получить два новых коммита и создать или обновить его featureA имя .

Давайте нарисуем этот процесс create-two-new-commits. Мы начинаем, как мы видели, с:

...--F--G--H  <-- master, featureA (HEAD), origin/master

Сначала вы сделали один новый коммит (обычным способом). Этот новый коммит получил новый уникальный идентификатор ha sh, отличный от идентификатора ha sh любого другого коммита в любой точке мира. 1 Мы просто назовем его I, и нарисуйте его:

...--F--G--H  <-- master, origin/master
            \
             I   <-- featureA (HEAD)

Обратите внимание, как новый коммит I указывает на существующий коммит H, и что имя featureA теперь указывает вместо I H. Никакой существующий коммит не изменился! Вы только что добавили новый коммит с новым ha sh ID и переместили имя ветви . Вот как растут ветви: в Git.

Затем вы сделали второй новый коммит:

...--F--G--H  <-- master, origin/master
            \
             I--J   <-- featureA (HEAD)

И наконец, вы использовали git push для отправки новых коммитов, I и J, к другому Git в origin. Вы попросили Git установить в своем репозитории имя featureA, указывающее на фиксацию J. Учитывая, что он сказал ОК, я сделал это ваш Git затем создал ваш origin/featureA, чтобы помнить, что их Git, в origin, теперь имеет featureA:

...--F--G--H  <-- master, origin/master
            \
             I--J   <-- featureA (HEAD), origin/featureA

Затем я переключаюсь на featureB и хочу получить sh два новых коммита, но коммиты в featureA являются частью featureB. Как мне переключиться на новую ветку featureB и начать «afre sh», которая была в состоянии до того, как я нажал два коммита?

Теперь, когда у нас есть все эти графические рисунки, ответ гораздо яснее , Нам просто нужно создать новое имя featureB так, чтобы оно указывало на существующий коммит H, такой же, как у master и origin/master name.

Два обычных способы создания нового имени ветви - использовать git branch или git checkout -b. Разница в том, что git branch создает имя и затем останавливается, в то время как git checkout -b создает имя, а затем git checkout для имени. Поскольку вам также нужен шаг git checkout, имеет смысл использовать комбинированную команду, но давайте выделим ее как отдельные шаги.

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

Прямо сейчас, HEAD присоединено к featureA и featureA очков для фиксации J. Поэтому, если вы просто создадите имя ветви с git branch featureB, новое имя будет указывать на коммит J. Но вы хотите, чтобы он указывал на фиксацию H.

Вы можете легко указать git branch использовать любой существующий коммит . Все, что вам нужно, это его sh ID или любое имя, которое указывает на этот коммит. Таким образом, вы можете запустить git log и найти фактический идентификатор * *1226* коммита H и ввести его - что довольно сложно сделать, хотя вырезать и вставить проще сделать правильно - или вы можете просто используйте любое из имен, которые все еще указывают на фиксацию H, например, master или origin/master:

git branch featureB master

. Это приводит к:

...--F--G--H  <-- master, featureB, origin/master
            \
             I--J   <-- featureA (HEAD), origin/featureA

Обратите внимание, что HEAD все еще присоединен к featureA, который все еще указывает на фиксацию J.

Теперь, когда существует featureB, мы можем использовать git checkout чтобы переключиться на него. Это заменит ваш index (который мы здесь не упомянули, так как этот ответ касается только названий ветвей) и рабочее дерево (о котором мы действительно не упомянули здесь) с содержимым коммита H при добавлении имени HEAD к имени featureB:

...--F--G--H  <-- master, featureB (HEAD), origin/master
            \
             I--J   <-- featureA, origin/featureA

Ваш текущий коммит теперь H; ваше имя текущей ветки теперь featureB; и вы готовы делать новые коммиты, в результате чего featureB будет включать новые коммиты, которые вы делаете.


1 Эта уникальность почему Git га sh ID такие большие и некрасивые. Они действительно уникальны на практике, но на самом деле только имеют , чтобы быть уникальными во всех Git хранилищах, которые когда-либо "встречались". Однако, поскольку SHA-1 считается небезопасным и «сломанным», Git перемещается в SHA-256, чтобы помочь сохранить это «уникальное значение для всех коммитов на Земле и в любом месте солнечной системы или галактики в будущем».

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...