Какой самый короткий способ поменять этапные и неустановленные изменения в git? - PullRequest
29 голосов
/ 26 августа 2010

Если некоторые изменения добавлены в индекс, а некоторые изменения не добавлены в индекс, как мне поменять местами эти два набора изменений?

Ответы [ 5 ]

13 голосов
/ 26 августа 2010

Кажется, что это проще всего сделать с временными коммитами.Когда вы делаете поэтапные и не постановочные коммиты, у вас есть возможность конфликтов при попытке изменить порядок изменений.

Сделайте коммит с поэтапными изменениями, создайте ветвь для последующего использования:

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 HEAD@{1} HEAD^

Наконец, сбросьте индекс на (изначально) неизмененные изменения:

git reset HEAD^

И переместите указатель ветви обратно в исходную ГОЛОВКУ:

git reset --soft HEAD^

Удалена временная ветвь:

git branch -D save-staged
5 голосов
/ 17 июня 2013

Это основано на ответе Вальтера Мундта , но работает лучше, когда создаются новые файлы.Это предназначено для использования в качестве сценария, например 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 голосов
/ 17 февраля 2011

Для решения более низкого уровня, вы можете использовать немного слесарного дела, чтобы напрямую общаться с индексом:

INDEXTREE=`git write-tree`
git add -A
WORKTREE=`git write-tree`
git checkout $INDEXTREE -- .
git clean -f
git read-tree $WORKTREE

Что делает, это создает пару временных объектов дерева в git store, один для индекса и один для рабочей копии. Затем он восстанавливает старый индекс и проверяет его в рабочем дереве. В заключение. он сбрасывает индекс к версии, представляющей старое рабочее дерево.

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

3 голосов
/ 26 августа 2010

Способ с патчами (он не работает для двоичных изменений):

Сохранение патчей как для промежуточных, так и для неустановленных состояний

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
3 голосов
/ 26 августа 2010

Чарльз Бейли имеет более полное решение , включающее коммиты и управление потенциальным разрешением конфликтов.

Изначально я пытался использовать только git stash, за исключением того, что я изначально упустил из виду, что git stash save сохранит и индекс (поэтапные изменения) и неустановленные изменения (что неудобно, когда вы хотите поменять содержимое индекса с неустановленными изменениями).

Поэтому я изменил следующий подход:

  • git commit -m "временная фиксация" (создать фиксацию для текущего индекса)
  • git stash (очевидно, что скрывает то, что еще не добавлено в индекс)
  • git reset --soft HEAD^ (сохранить ранее сохраненные файлы)
  • git stash снова
  • git stash pop stash@{1} (применяя не то, что вы только что спрятали, а то, что вы спрятали раньше, то есть начальные изменения, которые еще не были добавлены в индекс)
  • git add -A
  • git stash drop stash@{1} для очистки хранилища, которое мы ранее применяли (stash @ {0} по-прежнему содержит то, что изначально было в индексе)

В конце:

  • добавлено то, что не было добавлено в индекс.
  • то, что изначально было в индексе, спрятано
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...