Как вы говорите git, чтобы хранить индекс только? - PullRequest
57 голосов
/ 12 марта 2011

Я только что использовал "git add -p", чтобы добавить кучу изменений в индекс, и я только что понял, что пропустил изменение, которое должно было войти в предыдущий коммит.

Я могуне выполняйте --amend сейчас, потому что я добавил все эти новые изменения в индекс, и я не хочу использовать «git reset», чтобы удалить их все из индекса, так как их добавление займет много времениснова.

Что мне нужно, это что-то вроде 'git stash', который будет только хранить индекс - он должен оставить рабочие файлы в покое.Затем я могу спрятать индекс, добавить отсутствующее изменение, зафиксировать его, затем вытолкнуть тайник и вернуть мой индекс в прежнее состояние.

Не похоже, что 'git stash' может это сделать, но я что-то упустил?Спасибо!

Ответы [ 11 ]

31 голосов
/ 13 августа 2012

Самое близкое, что я нашел, это git stash --patch. Он проведет вас через каждое из изменений рабочего дерева и индекса, позволяя вам выбрать, что хранить.

http://www.kernel.org/pub/software/scm/git/docs/git-stash.html

23 голосов
/ 12 марта 2011

Самый простой способ - прекратить это изменение прямо сейчас, сделать свой новый коммит, затем создать второй коммит с тем изменением, которое вы хотите использовать для внесения поправок, и затем использовать git rebase -i, чтобы раздавить его с оригинальным HEAD.

В качестве альтернативы можно было бы сделать свой коммит, пометить его, откатить с помощью git reset HEAD^, добавить это одно изменение и изменить HEAD, а затем выбрать свой помеченный коммит вишней.

16 голосов
/ 19 января 2017

Почему бы не обмануть?

git stash --keep-index

, чтобы получить оттуда все, чего нет в индексе в настоящее время.Затем

git stash

, чтобы получить тайник только с тем, что поставлено.

git stash pop

первый тайник, добавьте свои изменения.Затем

git commit --amend ...
git reset --hard

, чтобы очистить рабочее дерево, а затем

git stash pop --index

, чтобы вернуть изменения в индекс.

10 голосов
/ 16 февраля 2017

git stash фактически создает коммит с содержимым индекса, а затем добавляет коммит с содержимым всех отслеживаемых файлов поверх него

Для просмотра: создайте тайник, затем запустите

git log --oneline --graph stash@{0}

Технически, когда вы копите, вы можете вернуть свой индекс через stash@{0}^2:

$ git show --name-only stash@{0}^2
$ git checkout stash@{0}^2 -- .

Вы также можете сохранить, а затем получить содержимое отслеживаемых, но не добавленных файлов:

# get the diff between what was indexed and the full stashed content :
$ git diff -p stash@{0}^2 stash@{0}  >  diff.patch
# apply this diff :
$ git apply diff.patch
9 голосов
/ 27 февраля 2013

Зафиксируйте ваш индекс, создайте фиксацию фикса и сделайте ребаз, используя autosquash:

git commit
git add -p                         # add the change forgotten from HEAD^
git commit --fixup HEAD^           # commits with "fixup! <commit message of HEAD^>"
git rebase --autosquash -i HEAD~3
5 голосов
/ 24 сентября 2017

magit для emacs позволяет вам сделать это командой magit-stash-index

5 голосов
/ 14 октября 2016

Это похоже на работу. Я не проверял его во всех ситуациях, чтобы убедиться в его надежности:

git commit -m _stash && git stash && git reset HEAD^ && git stash save  && git stash pop stash@{1}

Но он фактически временно фиксирует индекс, сохраняет рабочий каталог, отменяет фиксацию, чтобы вернуть индекс, сохраняет его как другой тайник, а затем снова восстанавливает исходный рабочий каталог из тайника.

Это упрощается добавлением псевдонима git:

[alias]
    istash = "!f() { git commit -m _stash && git stash && git reset HEAD^ && git stash save $1 && git stash pop stash@{1}; }; f"

Это позволяет мне использовать его как:

git istash [optional stash name]
2 голосов
/ 12 января 2016

Мне пришлось это сделать, и в итоге я использовал некоторые опции git stash, предназначенные для сценариев.Git stash create позволяет вам создавать (но не применять) объект stash (который включает в себя индекс).Хранилище Git Stash добавляет его в стек Git Stash без выполнения Git Reset - жестко, что Git Stash делает неявно.Это, по сути, позволяет вам спрятать индекс, добавив объект стека в стек и сбросив его вручную:

# This will add an entry to your git stash stack, but *not* modify anything
git stash store -m "Stashed index" $(git stash create)

# This will reset the index, without touching the workspace.
git reset --mixed 

Теперь вы, по сути, спрятали свой индекс и можете выполнить всплывающее окно git stash --index, когда вы закончите.

Одно предостережение: созданный объект-хранилище включает в себя как файлы, измененные в рабочей области, так и индекс, даже если вас беспокоит только индекс, так что есть возможностьконфликтует, когда вы пытаетесь извлечь содержимое из стека, даже если вы используете флаг --index (что означает «также применять индекс из тайника», а не «применять только индекс из тайника»).В этом случае вы можете выполнить «git reset --hard» перед извещением (поскольку изменения, которые вы сбрасываете, также совпадают с изменениями, которые вы извлекаете или применяете сразу после этого, это не так опасно, каккажется.)

1 голос
/ 05 декабря 2017
git stash -k
git stash
git stash apply stash@{1}
git stash drop stash@{1}
1 голос
/ 15 февраля 2015

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

(Примечание: я первоначально разместил это на https://stackoverflow.com/a/17137669/531021,, но, похоже, он применим и здесь.Это не совсем повторяющиеся вопросы, поэтому я думаю, что в обоих случаях это может быть возможным ответом)

#!/bin/sh

# first, go to the root of the git repo
cd `git rev-parse --show-toplevel`

# create a commit with only the stuff in staging
INDEXTREE=`git write-tree`
INDEXCOMMIT=`echo "" | git commit-tree $INDEXTREE -p HEAD`

# create a child commit with the changes in the working tree
git add -A
WORKINGTREE=`git write-tree`
WORKINGCOMMIT=`echo "" | git commit-tree $WORKINGTREE -p $INDEXCOMMIT`

# get back to a clean state with no changes, staged or otherwise
git reset -q --hard

# Cherry-pick the index changes back to the index, and stash.
# This cherry-pick is guaranteed to suceed
git cherry-pick -n $INDEXCOMMIT
git stash

# Now cherry-pick the working tree changes. This cherry-pick may fail
# due to conflicts
git cherry-pick -n $WORKINGCOMMIT

CONFLICTS=`git ls-files -u`
if test -z "$CONFLICTS"; then
    # If there are no conflicts, it's safe to reset, so that
    # any previously unstaged changes remain unstaged
    #
    # However, if there are conflicts, then we don't want to reset the files
    # and lose the merge/conflict info.
    git reset -q
fi

Вы можете сохранить вышеприведенный скрипт как git-stash-index где-нибудь на вашем пути, а затем вызвать егокак git stash-index

# <hack hack hack>
git add <files that you want to stash>
git stash-index

Теперь в тайнике есть новая запись, которая содержит только внесенные вами изменения, а ваше рабочее дерево по-прежнему содержит любые неустановленные изменения.

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

В этом случае любые такие конфликты будут оставлены в обычном не объединенномконфликтное состояние, так же как после вишни-слияния / слияния.

например

git init
echo blah >> "blah"
git add -A
git commit -m "blah"

echo "another blah" >> blah
git add -A
echo "yet another blah" >> blah

# now HEAD contains "blah", the index contains "blah\nanother blah"
# and the working tree contains "blah\nanother blah\nyetanother blah"

git stash-index

# A new stash is created containing "blah\nanother blah", and we are
# left with a merge conflict, which can be resolved to produce
# "blah\nyet another blah"
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...