Git pull после принудительного обновления
Я просто раздавил некоторые коммиты с git rebase
и сделал git push --force
(это зло, я знаю).
Теперь другие разработчики программного обеспечения имеют другую историю, и когда они делают git pull
Гит слит. Есть ли способ исправить это, кроме как сделать rm my-repo; git clone git@example.org:my-repo.git
?
Мне нужно что-то вроде противоположности git push --force
, но git pull --force
не дал ожидаемых результатов.
6 ответов
Чтобы получать новые коммиты
git fetch
Сброс
Вы можете сбросить коммит для локальной ветки, используя git reset
,
Чтобы изменить коммит локальной ветки:
git reset origin/master --hard
Будьте осторожны, как сказано в документации:
Сбрасывает индекс и рабочее дерево. Любые изменения в отслеживаемых файлах в рабочем дереве после
отбрасываются.
Если вы хотите сохранить какие-либо изменения, которые вы получили локально - сделайте --soft
Сброс вместо Который обновит историю коммитов для ветки, но не изменит какие-либо файлы в рабочем каталоге (и вы сможете потом их зафиксировать).
Rebase
Вы можете воспроизвести ваши локальные коммиты поверх любого другого коммита / ветки, используя git rebase
:
git rebase -i origin/master
Это вызовет rebase в интерактивном режиме, где вы можете выбрать способ применения каждого отдельного коммита, которого нет в истории, поверх которой вы перебираете.
Если коммиты вы удалили (с git push -f
) уже внесены в локальную историю, они будут перечислены как коммиты, которые будут применены повторно - их необходимо будет удалить как часть перебазирования, или они просто будут повторно включены в историю для ветви - и снова появятся в удаленная история при следующем нажатии.
Воспользуйтесь помощью git command --help
для более подробной информации и примеров по любой из вышеперечисленных (или других) команд.
Вытяните с перебазированием
Обычное извлечение - это выборка + слияние, но вам нужно получить выборку + перебазирование. Это вариант сpull
команда:
git pull --rebase
Это не исправит ответвления, в которых уже есть код, который вам не нужен (см. Ниже, как это сделать), но если они потянули какую-то ветку и теперь хотят, чтобы она была чистой (а не "впереди" origin/some-branch) тогда вы просто
git checkout some-branch # where some-branch can be replaced by any other branch
git branch base-branch -D # where base-branch is the one with the squashed commits
git checkout -b base-branch origin/base-branch # recreating branch with correct commits
Примечание. Вы можете объединить их, поставив && между ними.
Примечание 2: Флориан упомянул об этом в комментарии, но кто читает комментарии, когда ищет ответы?
Примечание 3: Если у вас есть зараженные ветви, вы можете создавать новые, основываясь на новой "тупой ветви", и просто выполнять коммиты "Cherry-pick".
Пример:
git checkout feature-old # some branch with the extra commits
git log # gives commits (write down the id of the ones you want)
git checkout base-branch # after you have already cleaned your local copy of it as above
git checkout -b feature-new # make a new branch for your feature
git cherry-pick asdfasd # where asdfasd is one of the commit ids you want
# repeat previous step for each commit id
git branch feature-old -D # delete the old branch
Теперь новая функция - это ваша ветка без лишних (возможно, плохих) коммитов!
Чтобы получить изменения из удаленного репозитория в локальное репозиторий:
git fetch
Переименуйте ветку отслеживания:
git branch -m <old-branch-name> <new-name>
Создайте новую локальную ветвь, отслеживающую удаленную ветку:
git checkout -b <old-branch-name>
Однолинейное решение
ниже команда потянет и принудительно обновит
git pull --rebase
TLDR:
git switch master
git pull
git branch -D featureBranch // careful! FORCE DELETE
git switch featureBranch
Итак, в вашем случае ветки уже отслеживаются локально. Убедитесь, что мастер извлечен. На мастереgit pull
достаточно для обновления всех ваших веток, включая ветку функций. Вы можете посмотреть сgit branch -vv
чтобы увидеть ветку, где находитсяgit push --force
произошло, вы увидите что-то вроде...ahead 2, behind 7...
Теперь сgit branch -D featureBranch
вы выполняете принудительное удаление вашей локальной ветки функций.
Последний шаг:git switch featureBranch
, который снова проверяет ранее извлеченную ветвь функции локально и настраивает ее для отслеживания удаленной ветки.