Если в индекс добавлены некоторые изменения, и есть некоторые изменения, которые не добавлены в индекс, как мне заменить эти два набора изменений?
Каков самый короткий способ обмена поэтапными и неустановленными изменениями в git?
Ответ 1
Он считает, что это проще всего сделать с временными коммитами. Когда вы выполняете поставленные и неустановленные коммиты, у вас есть возможность конфликтов при попытке изменить порядок изменений.
Сделайте фиксацию с поэтапными изменениями, создайте ветку для дальнейшего использования:
git commit -m "Saved staged"
git branch save-staged
Сделайте фиксацию с неустановленными изменениями (если неустановленные изменения включают новые файлы, вам может понадобиться явно указать git add
их):
git commit -a -m "Unstaged changes"
Восстановить неустановленные изменения на исходном HEAD (может включать разрешение конфликтов):
git rebase --onto HEAD^^ HEAD^
Восстановите поэтапные изменения на неустановленные изменения (может включать разрешение конфликтов):
git reset --hard save-staged
git rebase --onto [email protected]{1} HEAD^
Наконец, reset индекс для (первоначально) нестационарных изменений:
git reset HEAD^
И переместите указатель ветвления обратно в исходный HEAD:
git reset --soft HEAD^
Удалена временная ветка:
git branch -D save-staged
Ответ 2
Для решения более низкого уровня вы можете использовать немного сантехники, чтобы напрямую разговаривать с индексом:
INDEXTREE=`git write-tree`
git add -A
WORKTREE=`git write-tree`
git checkout $INDEXTREE -- .
git clean -f
git read-tree $WORKTREE
Что это значит, это построить пару временных древовидных объектов в хранилище git, один для индекса и один для рабочей копии. Затем он восстанавливает старый индекс и проверяет его на рабочем дереве. В заключение. он сбрасывает индекс в версию, представляющую старое рабочее дерево.
Я не тестировал это, поэтому я не уверен, насколько хорошо он обрабатывает добавленные файлы в индексе или рабочем дереве.
Ответ 3
Способ с патчами (он не работает для двоичных изменений):
Сохранение патчей как для поставленных, так и для нестационарных состояний
git diff >> unstaged.patch
git diff --cached >> staged.patch
Применить первоначально неустановленные изменения
git reset --hard
git apply unstaged.patch
Этап изменяется, кроме файлов патчей
git add -A
git reset -- staged.patch unstaged.patch
Применить первоначально выполненные изменения
git apply staged.patch
Удалить файлы патчей
rm staged.patch unstaged.patch
Ответ 4
Это основано на ответе Вальтера Мундта, но работает лучше при постановке новых файлов. Это предназначено для использования в качестве script, например. git-invert-index
#!/bin/sh
# first, go to the root of the git repo
cd `git rev-parse --show-toplevel`
# write out a tree with only the stuff in staging
INDEXTREE=`git write-tree`
# now write out a tree with everything
git add -A
ALL=`git write-tree`
# get back to a clean state with no changes, staged or otherwise
git reset -q --hard
git clean -fd
# apply the changes that were originally staged, that we want to
# be unstaged
git checkout $INDEXTREE -- .
git reset
# apply the originally unstaged changes to the index
git diff-tree -p $INDEXTREE $ALL | git apply --index --reject
Ответ 5
Charles Bailey имеет более полное решение, включающее фиксации и управление возможным разрешением конфликта.
Я пытаюсь использовать только git stash
, за исключением того, что я сначала забыл, что git stash
save сохранит как индекс, так и личные файлы (что неудобно, если вы хотите поменять индексный контент на содержимое личных файлов )
Вы можете:
-
git commit
-m "temp commit" (создать фиксацию для текущего индекса) -
git stash
(очевидно, что он еще не добавлен в индекс) -
git reset --soft HEAD^
(сохранить ранее сохраненные файлы) -
git stash
снова -
git drop [email protected]{1}
(применяя не то, что вы только что спрягли, а то, что вы спрятали до этого, то есть первоначальные изменения, которые еще не были добавлены в индекс) -
git add -A
В конце:
- то, что изначально было в индексе, заканчивается спрятанным
- теперь добавлено то, что не добавлено в индекс.