Переместить файлы между коммитами
У меня есть два последовательных коммита, где-то в локальной истории, и один файл был ошибочно добавлен во второй. Я хочу исправить ситуацию.
Я не понимаю, как я должен использовать интерактивный ребаз. я сделал git rebase -i HEAD~10
и выбрали для редактирования коммит с файлом, чтобы проверить его оттуда. Я использую git guit, но не вижу файлов в области коммита. Я могу изменить предыдущий коммит, после чего я вижу файлы. Но я не могу добавить неуместный файл в этот предыдущий коммит, так как не вижу файла в текущем коммите, с которого можно начать.
5 ответов
Если я не ошибаюсь, вам нужно перенести какое-то изменение, которое было включено в коммит 2, в коммит 1.
Я считаю, что самый простой способ сделать это - выполнить две последовательные интерактивные перебазировки.
В первом случае вы делите коммит 2 на два коммита: первый, включающий только изменения, которые вы хотите переместить, и второй, включающий все остальные. Теперь у нас есть коммиты 1, 2.1 и 2.2.
Затем вы снова делаете ребазинг, и на этот раз решите раздавить коммит 2.1 в 1.
Таким образом, при перебазировании выберите для редактирования как коммит, в который вы добавили файл по ошибке, так и тот, к которому вы хотите добавить его в указанном порядке. Если файл находится в более позднем коммите, но должен быть в более раннем, вам придется изменить порядок строк. Например, я начинаю с
pick 8de731b Commit with missing file.
pick bbef925 Commit with too many files.
pick 52490ce More history.
Мне нужно изменить это на
edit bbef925 Commit with too many files.
edit 8de731b Commit with missing file.
pick 52490ce More history.
Затем,
# In the commit containing an extra file
git reset HEAD^ badfile.c
git commit --amend
git rebase --continue
# Now in the commit to add it to
git add badfile.c
git commit --amend
git rebase --continue
К сожалению, при редактировании истории в одной ветке я не знаю способа избежать редактирования истории во всех ветках. Перебазирование должно быть сделано как можно раньше, чтобы избежать подобных проблем. В моем простом случае я могу объединить master и другую ветку, но коммиты не сливаются, тогда я должен перебазировать master, переупорядочить и раздавить коммиты следующим образом:
pick 7cd915f Commit with missing file.
fixup 8de731b Commit with missing file. #This was the higher of the two entries
pick 8b92c5a Commit with too many files.
fixup bbef925 Commit with too many files. #This was the higher of the two entries
pick 94c3f7f More history.
fixup 52490ce More history. #This was the higher of the two entries
Позднее редактирование: я только заметил, что я случайно переупорядочил историю коммитов как перенос из моего исходного ответа. Обмен строк в ребазе меняет порядок, который вы делаете; после редактирования вы можете сделать ребаз и снова поменять их, чтобы вернуться к исходному порядку фиксации.
Поскольку я часто сталкиваюсь с этой проблемой, я написал сценарий для этого. Работает полностью автоматически. Вы можете найти это на Github. Скопируйте его в локальную файловую систему, добавьте в PATH, и вы сможете запустить его как:
mv-changes <source-commit> <destination-commit> <path>...
Вы также можете запустить скрипт в оболочке Git-Bash в Windows.
Обратите внимание, что если есть изменения <path>
в промежуточных коммитах между source-commit
а также destination-commit
, она не будет работать.
Более подробная информация представлена здесь.
Сначала возьмите информацию о короткой истории
> git log --oneline -n 3 --decorate=short
333333 (HEAD -> work_AAA) added test /*file is updated here*/
222222 corrected bug
111111 (origin/master, origin/HEAD, master) version XXX
так что мы можем перебазировать и остановиться на коммите 22222
> git rebase -i master
pick 22222 corected bug
pick 33333 added test
изменить на:
edit 22222 corected bug
pick 33333 added test
тогда вы будете в режиме обновления в коммите 22222, он показывает что-то вроде этого:
Stopped at 22222... corrected bug
You can amend the commit now, with
git commit --amend
Once you are satisfied with your changes, run
git rebase --continue
здесь скопируйте файл из коммита 3 в коммит 2
git show 33333:path/to/file > path/to/file
исправить коммит 2 и продолжить ребаз
git commit --amend --no-edit path/to/file
git rebase --continue
Готово!
У меня была такая же проблема, и я хочу объяснить, что я сделал.
В коммит AI добавлен файл f, который мне пришлось удалить в следующем коммите B.
Теперь я хотел избавиться от файла в обоих коммитах, но также хотел избежать разделения коммита, потому что было задействовано много других файлов. я сделал это
- восстановить файл
- добавьте его снова в коммит ADD
- удалить его в коммит REM - теперь есть история A - B - ADD - REM
- Сквош коммит А с REM - тогда файл исчезает из А и Б
- drop commit ADD - теперь файл исчез, как и должно быть
Возможно, это странное решение, но для меня это сработало.
Пожалуйста, прокомментируйте, если вы чувствуете, что это плохо по каким-то причинам.