Git: Как перезаписать все локальные изменения при слиянии?

Вот ситуация. Я работаю над ветвью master. Я создаю файл1 и фиксирую. Я создаю файл2 и фиксирую. Упс. Возможно, я захочу использовать файл2, когда-нибудь, но это определенно не то, что должно быть помещено в главную ветку. Чтобы я не потерял файл2, я использую

git checkout head~1
git branch new-branch
git checkout new-branch

чтобы я мог продолжать развиваться. Я добавляю file3 в new-branch. Если вы обратили внимание, у меня есть две ветки: master, которая содержит "file1" и "file2" и new-branch, которая содержит "file1" и "file3".

Настало время получить изменения, которые я внес в главную ветвь. Какой лучший способ сделать это? Я определенно хочу, чтобы глава ветки master указывал на файлы, как они появляются в new-branch, но я также не хочу потерять работу, которую я сделал в файле2, выполнив reset, в случае Я хочу использовать его.

Имейте в виду, что это упрощение. Вместо трех файлов у меня есть десяток файлов с десятками строк кода, которые меняются по всему месту с несколькими коммитами. Я, конечно, надеюсь, что решение состоит не в том, чтобы выполнить слияние/проверку файлов за файлом, потому что это было бы огромной болью.

Любые идеи?

Ответы

Ответ 1

Я работаю над главной ветвью. я создать файл1 и зафиксировать.

date >file1
git add file1
git commit -m 'added file1'

Я создаю файл2 и фиксирую.

date >file2
git add file2
git commit -m 'added file2'

Упс. Я могу использовать файл2, когда-нибудь, но это определенно не то, что нужно положить в мастер-ветвь.

К сожалению. Очень просто. Создайте новую ветку, где вы находитесь:

git checkout -b savingfile2

Это заставит файл2 изменить фиксацию на savingfile2. Теперь вернитесь назад и отпустите один шаг на главном

git checkout master
git reset --hard HEAD~1

В этот момент коммиты, ведущие к мастеру, будут отражать добавление файла1, и дополнительная фиксация между master и savefile2 будет добавлением файла2 к этому.

Если вы сделаете больше изменений в master, а затем хотите вернуть файл2 в конце концов, вы захотите переустановить эту боковую ветвь на новый мастер:

date >file3
git add file3
git commit -m 'adding file3'
date >file4
git add file4
git commit -m 'adding file4'

И теперь мы, наконец, хотим file2:

git checkout savingfile2
git rebase master # might need to fix conflicts here
git checkout master
git merge savingfile2 # will be a fast-forward
git branch -d savingfile2 # no need any more

Это должно сделать это.

Ответ 2

Что вы должны сделать, так это то, что вы должны были сделать, когда заметили свою ошибку при выполнении файла2: отмените фиксацию (вместо создания новой ветки):

git checkout master
git reset HEAD^

Это оставляет файл2 невосстановленным и невредимым и возможные изменения недействительны. Затем вы должны (иметь) stash (ed) немедленные изменения в случае, если вы хотите использовать их позже:

git stash save "modifications that should not be in the master branch"

Stashing избавляется от каких-либо локальных изменений, что позволяет master указывать на new-branch:

git merge new-branch
Цель заключалась в том, чтобы устранить расхождение между двумя ветвями, т.е. сделать master предком new-branch. Таким образом, фактическое слияние не должно происходить, а последняя команда просто ускорит переадресацию ветки master (при отсутствии локальных изменений).

Ответ 3

Поскольку вы не выполнили оптимальный рабочий процесс, описанный Tomi Kyöstilä, но также, поскольку вы не 'публиковать (нажимать) что-нибудь еще, почему бы не переключить две ветки?
(при условии, что все совершено)

master и new-branch являются лишь некоторыми указателями на некоторые SHA1:

$ git checkout master              #start from master
$ git branch tmp                   # tmp points on master HEAD
$ git checkout new-branch          # switch to new-branch
$ git branch -f master new_branch  # master points at new-branch HEAD
$ git checkout tmp                 # switch back to *former* master branch
$ git branch -f new_branch tmp     # new-branch points at former master HEAD
$ git checkout master              # go to new master
$ git branch -D tmp                # remove tmp pointer

... и все готово.
(отказ от ответственности: еще не проверено, поэтому старайтесь с осторожностью;))

См: