#git #git_rebase
Есть коммит состоящий из изменений пары файлов и удаления папки (не пустой). Сейчас мне нужно изменить этот коммит перед push так, чтобы та папка все же осталась, изменения коснулись только кода Я пробую git rm --cached foldername git rm -r --cached foldername но получаю did not match any files Как можно исправить ситуацию?
Ответы
Ответ 1
Можно просто вытащить эту папку обратно из предыдущего коммита: git checkout HEAD^ -- foldername Она будет уже в индексе, вам останется только заменить коммит-верхушку новым, в котором эта папка есть: git commit --amend Стандартное предупреждение для читателей: --amend переписывает историю, не используйте на коммитах, которые уже публиковали в общие ветки. Вопрос этого и требует, просто подчёркиваю лишний раз, пока кому-нибудь не пришлось с грустным лицом искать свои коммиты в рефлоге.Ответ 2
Делается это проще всего через интерактивный rebase. Внимание! Сначала рекомендуется сделать полную копию всей папки и файлов, чтобы была возможность предварительно проделать изменения на копии. Промоделируем ситуацию. У нас есть какой-то репозиторий: [www]$ cd ~ [~]$ mkdir test && cd test && git init Initialized empty Git repository in /home/ak/test/.git/ [test]$ touch 123.txt [test]$ git add . [test]$ git commit -m "123.txt" [master (root-commit) 6054429] 123.txt 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 123.txt [test]$ mkdir folder [test]$ touch folder/1.txt [test]$ touch folder/2.txt [test]$ touch aaa.txt [test]$ git add . [test]$ git commit -m "Create some folder and files" [master c0b67ad] Create some folder and files 3 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 aaa.txt create mode 100644 folder/1.txt create mode 100644 folder/2.txt [test]$ Во время активной разработки мы сделали коммит Temp commit, который нам казался правильным. Он содержит удаление папки и добавление какого-то файла: [test]$ git status # On branch master nothing to commit, working directory clean [test]$ git rm -r folder/ rm 'folder/1.txt' rm 'folder/2.txt' [test]$ touch bbb.txt [test]$ git add -A [test]$ git commit -m "Temp commit" [master 021ec06] Temp commit 2 files changed, 0 insertions(+), 0 deletions(-) rename folder/1.txt => bbb.txt (100%) delete mode 100644 folder/2.txt [test]$ И потом мы решили убрать из этого коммита удаление папки. Входим в режим интерактивного rebase: [test]$ git rebase -i HEAD~2 pick c0b67ad Create some folder and files pick 021ec06 Temp commit # Rebase 6054429..021ec06 onto 6054429 # # Commands: # p, pick = use commit # r, reword = use commit, but edit the commit message # e, edit = use commit, but stop for amending # s, squash = use commit, but meld into previous commit # f, fixup = like "squash", but discard this commit's log message # x, exec = run command (the rest of the line) using shell # # These lines can be re-ordered; they are executed from top to bottom. # # If you remove a line here THAT COMMIT WILL BE LOST. # # However, if you remove everything, the rebase will be aborted. # # Note that empty commits are commented out ~ ~ ~ "~/test/.git/rebase-merge/git-rebase-todo" 20L, 673C Нам нужно заменить строку pick 021ec06 Temp commit на e 021ec06 Temp commit и выйти с сохранением. (Основы редактирования в vi не рассматриваются, но я бы сделал как j 4x i e ESC :wq). Мы остановились на редактировании коммита: [test]$ git rebase -i HEAD~2 Stopped at 021ec06... Temp commit You can amend the commit now, with git commit --amend Once you are satisfied with your changes, run git rebase --continue [test]$ Теперь мы должны сделать следующие операции: [test]$ git reset HEAD~ Unstaged changes after reset: D folder/1.txt D folder/2.txt Мы просто возвращаем из stage area обратно. Посмотрите что мы получилось: [test]$ git status # HEAD detached at c0b67ad # You are currently splitting a commit while rebasing branch 'master' on '6054429'. # (Once your working directory is clean, run "git rebase --continue") # # Changes not staged for commit: # (use "git add/rm..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # deleted: folder/1.txt # deleted: folder/2.txt # # Untracked files: # (use "git add ..." to include in what will be committed) # # bbb.txt no changes added to commit (use "git add" and/or "git commit -a") [test]$ Мы можем теперь добавить только то в коммит, что хотим и не добавлять то, что не хотим (удаление папки): [test]$ git add bbb.txt [test]$ git commit -m "New commit" [detached HEAD 666dc98] New commit 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 bbb.txt Удаление папки осталось: [test]$ git status # HEAD detached from c0b67ad # You are currently splitting a commit while rebasing branch 'master' on '6054429'. # (Once your working directory is clean, run "git rebase --continue") # # Changes not staged for commit: # (use "git add/rm ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # deleted: folder/1.txt # deleted: folder/2.txt # no changes added to commit (use "git add" and/or "git commit -a") [test]$ Но оно не входит ни в какие коммиты. Мы даём команду на продолжение rebase и видим, что нужно положить на stash удаление: [test]$ git rebase --continue folder/1.txt: needs update folder/2.txt: needs update You must edit all merge conflicts and then mark them as resolved using git add [test]$ git stash Saved working directory and index state WIP on (no branch): 666dc98 New commit HEAD is now at 666dc98 New commit [test]$ git status # HEAD detached from c0b67ad # You are currently editing a commit while rebasing branch 'master' on '6054429'. # (use "git commit --amend" to amend the current commit) # (use "git rebase --continue" once you are satisfied with your changes) # nothing to commit, working directory clean [test]$ git rebase --continue Successfully rebased and updated refs/heads/master. [test]$ В принципе, удаление папки нам не нужно, чистим карман: [test]$ git stash list stash@{0}: WIP on (no branch): 666dc98 New commit [test]$ git stash drop Dropped refs/stash@{0} (73ad2a9ff3b4304a5106a259cb14135eaa9a711c) [test]$ И смотрим историю: [test]$ git status # On branch master nothing to commit, working directory clean [test]$ git log commit 666dc983ae2ecf894e76c83d5c061a9449d672f4 Author: ak at server Date: Fri Dec 1 21:23:02 2017 +0300 New commit commit c0b67ad5e1f72536891e8c23a72746c83e103e3c Author: ak at server-43 Date: Fri Dec 1 21:08:11 2017 +0300 Create some folder and files commit 605442916d9a5757f2d4ad5847205a75711c9cab Author: ak at server-43 Date: Fri Dec 1 21:06:38 2017 +0300 123.txt [test]$ Всё, как нам и надо было: [test]$ git show HEAD commit 666dc983ae2ecf894e76c83d5c061a9449d672f4 Author: ak at server-43 Date: Fri Dec 1 21:23:02 2017 +0300 New commit diff --git a/bbb.txt b/bbb.txt new file mode 100644 index 0000000..e69de29 [test]$ Альтернативный способ для тех, кто будет читать тему -- это тот способ, который кратко описывал топикстартер + дополнительный пункт с объединением коммитов в один. Проверить, что нет незакоммиченных изменений (чтобы потом не было мучительно больно, когда после reset --hard пропадут файлы) Становимся на коммит ПЕРЕД коммитом, когда были удалены файлы: git reset -- hard HEAD~5 Получаем состояние, в котором файлы не были удалены. Сохраняем их в какую-нибудь директорию вне гита. Возвращаемся назад git reset --hard HEAD@{1} (тут более логично смотреть reflog, написано из расчёта, что больше никаких команд не делали. мы понимаем, что есть незапушенные коммиты и их можно потерять, если что-то сделать неаккуратно) Подкладываем папку на место и коммитим её. При необходимости объединяем (squash) два идущих подряд коммита (первый - - с удалением папки, второй -- с её добавлением) Пример можно посмотреть в этой теме. Ответ 3
Решил проблему откатом git reset --hard HEAD^ и повторным внесением изменений с комитом в эту ветку. Решение так себе, но рабочее. Уверен, есть что-то куда более правильное.
Комментариев нет:
Отправить комментарий