Перемещение зафиксированных (но не выдвинутых) изменений в новую ветвь после извлечения

Я выполнил справедливую работу ( "Ваша ветка впереди" происхождение/мастер "на 37 коммитов" ), которая действительно должна была входить в свою ветвь, а не в master. Эти коммиты существуют только на моей локальной машине и не были нажаты на origin, но ситуация несколько осложняется тем, что другие разработчики нажимают на origin/master, и я потянул эти изменения.

Как мне ретроактивно переместить мои 37 локальных коммитов на новую ветку? Основываясь на документах, кажется, что git rebase --onto my-new-branch master или ...origin/master должны это сделать, но оба просто дают мне ошибку "фатальный: требуется одна ревизия". man git-rebase ничего не говорит о предоставлении исправления для rebase, и его примеры этого не делают, поэтому я понятия не имею, как разрешить эту ошибку.

(Обратите внимание, что это не дубликат Перемещение существующей, неработающей работы в новую ветвь в Git или Как объединить мои локальные незафиксированные изменения в другой ветвь Git?), поскольку эти вопросы касаются незафиксированных изменений в локальном рабочем дереве, а не изменений, которые были совершены локально.)

Ответ 1

Это должно быть хорошо, поскольку вы еще не нажали свои коммиты в другом месте, и вы можете переписать историю своего ветки после origin/master. Сначала я запустил git fetch origin, чтобы убедиться, что origin/master обновлен. Предполагая, что вы в данный момент находитесь в master, вы должны иметь возможность:

git rebase origin/master

..., который будет воспроизводить все ваши коммиты, которые не находятся в origin/master на origin/master. По умолчанию действие rebase состоит в том, чтобы игнорировать комманды слияния (например, те, которые были добавлены вашим git pull), и он просто попытается применить патч, введенный каждым вашим коммитом, на origin/master. (Возможно, вам придется разрешить некоторые конфликты на этом пути.) Затем вы можете создать свою новую ветку на основе результата:

git branch new-work

... и затем reset ваш master вернуться к origin/master:

# Use with care - make sure "git status" is clean and you're still on master:
git reset --hard origin/master

При выполнении такого рода манипулирования ветвями с помощью git branch, git reset и т.д. Мне полезно часто просматривать граф фиксации с помощью gitk --all или аналогичного инструмента, просто чтобы убедиться, что я понимаю, где все различные ссылки указывают.

В качестве альтернативы вы могли бы просто создать ветвь темы, основанную на том, где находится ваш мастер (git branch new-work-including-merges), а затем reset master, как указано выше. Однако, поскольку ваша ветка темы будет включать в себя слияния из origin/master, и вы еще не изменили свои изменения, я бы предложил сделать перестановку, чтобы история была более аккуратной. (Кроме того, когда вы, в конце концов, соедините свою ветку темы с мастером, изменения будут более очевидными.)

Ответ 2

Если у вас низкое количество коммитов и вам все равно, если они объединены в один мегакмит, это работает хорошо и не так страшно, как при выполнении git rebase:

разархивируйте файлы (замените 1 на число коммитов)

git reset --soft HEAD~1

создать новую ветку

git checkout -b NewBranchName

добавить изменения

git add -A

сделать коммит

git commit -m "Whatever"

Ответ 3

Я придерживался той же проблемы. Я нашел самое простое решение, которое мне нравится делиться.

1) Создайте новую ветку с изменениями.

git checkout -b mybranch

2) Нажмите новый код ветвления на удаленном сервере.

git push origin mybranch

3) Возврат к главной ветке.

git checkout master

4) Reset код главной ветки с удаленным сервером и удалить локальную фиксацию.

git reset --hard origin/master

Ответ 4

Еще один способ предполагать branch1 - это ветка с фиксированными изменениями branch2 - желательная ветвь

git fetch && git checkout branch1
git log

выберите идентификаторы фиксации, которые необходимо переместить

git fetch && git checkout branch2
git cherry-pick commit_id_first..commit_id_last
git push

Теперь отмените разблокированные коммиты из начальной ветки

git fetch && git checkout branch1
git reset --soft HEAD~1

Ответ 5

Как насчет:

  • От ветвления от текущего HEAD.
  • Убедитесь, что вы находитесь на хозяине, а не на своей новой ветке.
  • git reset вернитесь к последнему фиксации, прежде чем приступать к изменениям.
  • git pull, чтобы повторно удалить удаленные изменения, которые вы выбрали с помощью reset.

Или это произойдет, когда вы попытаетесь повторно объединить ветку?

Ответ 6

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

  1. git log
  2. git diff {previous to last commit} {latest commit} > your_changes.patch
  3. git reset --hard origin/{your current branch}
  4. git checkout -b {new branch}
  5. git apply your_changes.patch

Я могу себе представить, что есть более простой подход к первым и вторым шагам.

Ответ 7

  • Оформить заказ свежих копий источников

    git clone ........

  • Сделать ветку из желаемой позиции

    git checkout {position} git checkout -b {branch-name}

  • Добавить удаленный репозиторий

    git remote add shared ../{original sources location}.git

  • Получить удаленные источники

    git fetch shared

  • Оформить требуемую ветку

    git checkout {branch-name}

  • Объединить источники

    git merge shared/{original branch from shared repository}

Ответ 8

Для меня это был лучший способ:

  • Проверить изменения и слить конфликты git fetch
  • Создайте новую ветку git branch my-changes и нажмите на удаленный
  • Изменить восходящий поток на новую созданную ветку git master -u upstream-branch remotes/origin/my-changes
  • Нажмите свои коммиты на новую ветку вверх.
  • Вернитесь к предыдущему восходящему потоку git branch master --set-upstream-to remotes/origin/master

Ответ 9

Более простой подход, который я использовал (предполагая, что вы хотите переместить 4 коммита):

git format-patch HEAD~4

(посмотрите каталог, из которого вы выполнили последнюю команду для 4 файлов .patch)

git reset HEAD~4 --hard

git checkout -b tmp/my-new-branch

Тогда:

git apply /path/to/patch.patch

В любом порядке, который вы хотели.

Ответ 10

Вот гораздо более простой способ:

  1. Создать новую ветку

  2. В новой ветке сделайте git merge master - это объединит ваши зафиксированные (не отправленные) изменения с вашей новой веткой

  3. Удалите свою локальную главную ветвь git branch -D master. Используйте -D вместо -d, потому что вы хотите принудительно удалить ветку.

  4. Просто сделайте git fetch в своей мастер-ветке и git pull в своей мастер-ветке, чтобы убедиться, что у вас есть последний код вашей команды.