Зберігаючи лише нестадійні зміни в Git


229

Я хотів би виконати наступний робочий процес:

  1. Додайте зміни на сцені.
  2. Закрийте всі інші зміни, які не були інсценовані.
  3. Виконайте якісь речі з етапами (наприклад, будуйте, виконайте тести тощо)
  4. Нанесіть купіль.

Чи є спосіб зробити крок 2?

Приклад

 echo "123" > foo
 git add foo # Assumes this is a git directory
 echo "456" >> foo
 git stash
 cat foo # Should yield 123

Чому б не здійснити зміни після їх постановки?
Shizzmo

3
IIRC --keepindex робить саме це
sehe

4
Тому що, якщо, скажімо, збір не вдається, я не хочу цього робити. Я знаю, що можу видалити комісію, але я хотів би зробити це без комісії, якщо це можливо.
Унапіедра

Sehe, дякую. Я можу підтвердити це. Боже, я подивився посібник на сайті linux.die.net/man/1/git-stash, який застарів. man git stashнабагато краще.
Unapiedra

це --keke-index, fwiw.
jaf0

Відповіді:


288

git stash saveє варіант, --keep-indexякий робить саме те, що вам потрібно.

Отже, біжи git stash save --keep-index.


9
Правда. Я продовжувати використовувати saveз git stash. Можливо, саме програміст в мені наполягає на шануванні симетрії застосувати / поп. :)
vhallac

104
Примітка. Це все ще приховує всі ваші зміни; Єдина відмінність від звичайної git stash saveполягає в тому, що вона залишає і вже поетапні зміни у вашій робочій копії. У робочому процесі над цим буде добре працювати, оскільки ви просто застосовуєте копію зверху до локальної копії, яка вже має половину змін скриньки (який git досить розумний, щоб ігнорувати). Але якщо ви відредагуєте код перед повторним застосуванням сховища, потенційно ви можете побачити конфлікти злиття, коли перейдете до заявки. Фій.
peterflynn

2
@ytpete Це мене так багато разів вкусило. Я дуже хотів би, щоб git міг приховати лише те, чого ти не зберігаєш ... Я часто вчиняю речі, а потім роблю повну сховку, знаючи, що я можу, git commit --ammendякщо є проблеми в тому, що я вчинив.
rjmunro

1
--amend(а не --ammend)
Rhubbarb

19
Це рішення не працює для мене через проблеми, описані петерфлінном. Це не гарна відповідь на питання, оскільки воно все ще приховує поетапні зміни. Хтось отримав краще рішення?
user643011

43

Це може бути зроблено в 3 етапи: збережіть поетапні зміни, приховайте все інше, відновіть індекс із поетапними змінами. Що в основному:

git commit -m 'Save index'
git stash push -u -m 'Unstaged changes and untracked files'
git reset --soft HEAD^

Це зробить саме те, що ви хочете.


3
Примітка: -uтакож зберігає відслідковувані файли.
ma11hew28

Цей підхід по суті дублює те, що git stash save --keep-indexробить набагато більше роботи. Я не бачу жодних переваг.
Ініго

1
@vas Ні, підхід не дублює це. Дивіться коментар peterflynn до прийнятої відповіді.
Олександр Клауер

28
git stash save --keep-index

Також, Re:

Чому б не здійснити зміни після їх постановки? - Гомілка

Відповідь: Тому що ви завжди повинні перевіряти перевірений код :) Це означає, що вам потрібно запустити тести лише з тими змінами, які ви збираєтесь зробити

Все це, крім того, що, звичайно, як досвідчений програміст, ви маєте вроджене бажання перевірити та переглянути лише ті зміни - лише частково жартуєте


14

З git version 2.7.4вами ви можете:

git stash save --patch

gitПопросить вас додати чи ні змін в притон.
А ви тоді просто відповідаєте yабоn

Ви можете відновити робочий каталог, як це робите завжди:

git stash pop

або, якщо ви хочете зберегти зміни в сховищі:

git stash apply

Це круто. Це трохи трудомістко, але принаймні ви можете пропустити та додати цілі файли.
Дастін Опреа

5

Розширюючи попередні відповіді, я іноді маю складний набір змін, але бажаю спершу внести окремі зміни. Наприклад, я, можливо, помітив помилку або інший неправильний код, який хотів би виправити до моїх поетапних змін. Один з можливих маршрутів:

спочатку сховайте все, але залиште поетапні зміни недоторканими

$ git stash save --keke-index [--include-unntracked]

тепер також сховайте поетапні зміни окремо

$ git скринька збереження

внести зміни для виправлення; і тест; вчинити їх:

$ git add [--інтерактивний] [--patch]

$ git commit -m "виправити ..."

тепер відновіть попередньо поетапні зміни:

$ git stash pop

Вирішіть будь-які конфлікти та зауважте, що якщо конфлікти були, git застосував, але не скинув цю верхню скриньку.

(... Після цього введіть поетапні зміни та відновіть приховування всіх інших змін та продовжте ...)


4

Щоб додати непризначені (не додані для фіксації) файли в сховище, виконайте таку команду:

git stash -k

Потім ви можете скопіювати поетапні файли. Після цього ви можете отримати останні збережені файли за допомогою команди:

git stash pop

4

Зберігати лише робоче дерево (без змін) у Git складніше, ніж має бути. Прийнята відповідь приховує нестандартні зміни, але також приховує поетапні зміни (і залишає їх також поетапними), що рідко є тим, що ви хочете.

Цей псевдонім добре працює:

stash-working = "!f() { \
  git commit --quiet -m \"temp for stash-working\" && \
  git stash push \"$@\" && \
  git reset --quiet --soft HEAD~1; }; f"

Він тимчасово здійснює поетапні зміни, створює сховище з решти змін (і дозволяє додаткові аргументи, такі як --include-untrackedі --messageпередаватись як псевдонімні аргументи), а потім скидає тимчасове зобов’язання для повернення поетапних змін.

Це схоже на @Simon Кнапп відповідь , але з деякими незначними відмінностями - він використовує --quietна тимчасові заходи , вжиті, і він приймає будь-яку кількість параметрів для схованки push, а не жорсткого кодування -m, і він додає --softдо фіналу скинути, щоб індекс залишився таким, як він почався.

Для протилежної проблеми приховування лише поетапних змін (псевдонім stash-index) дивіться цю відповідь .


2

Ще одна порада, пов’язана з питанням:

Коли ви фактично приховуєте нестандартні зміни, використовуючи

$ git stash save --keke-індекс

Ви можете надіслати повідомлення сховано, щоб, коли ви робите git stash listце, було більш очевидно, що ви приховували раніше, особливо якщо ви дотримуєтесь цієї операції при подальшому збереженні. Наприклад

$ git stash save --keke-індекс "зміни ще не встановлено"

(хоча насправді він містить усі зміни, як зазначено в інших відповідях).

Наприклад, вищезазначене може негайно слідувати:

$ git stash save "поетапні зміни для функції X"

Але будьте обережні, що ви потім не можете їх використовувати

$ git stash застосовує "stash @ {1}" ### ✘ не зовсім робить те, що ви хочете

відновити лише нестандартні зміни.


2

У Git немає команди, яка приховує лише ваші незмінені зміни.

Однак Git дозволяє вказати, які файли потрібно зберігати.

git stash push --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

Якщо ви хочете лише приховати певні зміни в цих файлах, додайте цю --patchопцію.

git stash push --patch --message 'Unstaged changes' -- app/controllers/products_controller.rb test/controllers/products_controller_test.rb

Ця --include-untrackedопція дозволяє зберігати відслідковувані файли.

git stash push --include-untracked --message 'Untracked files' -- app/controllers/widgets_controller.rb test/controllers/widgets_controller_test.rb

Запустіть git help stash(або man git-stash) для отримання додаткової інформації.

Примітка: Якщо ваші нестандартні зміни досить неорганізовані, відповідь @ alesguzik, ймовірно, простіше.


0

Сучасна форма цієї команди є git stash push [--] [<pathspec>...], оскільки Git 2.16+ ( git stash saveзастарілий )

Ви можете комбінувати його із формою підстановки, наприклад:

git stash push --all --keep-index ':(glob)**/*.testextension' 

Але це не добре працює з Git для Windows, поки Git 2.22 (Q2 2019) див. Випуск 2037 , враховуючи, що git stashвін був реалізований на C (замість сценарію оболонки)

Див. Команду 7db9302 (11 березня 2019 року) від Томаса Гаммерера ( tgummerer) .
Див. Команду 1366c78 , вчинення 7b556aa (07 березня 2019) Йоганнеса Шинделіна ( dscho) .
(Об'єднав Хуніо С Хамано - gitster- у комітеті 0ba1ba4 , 22 квітня 2019 р.)

вбудований stash: :(glob)знову обробіть траєкторії

При передачі списку шляхових спекуляцій до, скажімо, git addнам потрібно обережно використовувати оригінальну форму, а не проаналізовану форму шляхів.

Це має значення, наприклад, при дзвінку

git stash -- ':(glob)**/*.txt'

де оригінальна форма включає :(glob)префікс, а розібрана форма - ні.

Однак у вбудованій git stashформі ми передали проаналізовану (тобто неправильну) форму і git addне змогли б отримати повідомлення про помилку:

fatal: pathspec '**/*.txt' did not match any files

на етапі, коли git stashвипадають зміни з робочого дерева, навіть якщо вони refs/stashбули фактично успішно оновлені.


0

Я використовую псевдонім, який приймає рядок, який слід використовувати як повідомлення до запису скриньки.

mystash = "!f() { git commit -m hold && git stash push -m \"$1\" && git reset HEAD^; }; f"

Котрий:

  • здійснює все в індексі,
  • приховує те, що змінюється в робочому дереві (можна, звичайно, додати -uабо -a),
  • скидає останнє зобов’язання назад у робочу спробу (можливо, захочеться використовувати його, --softщоб зберегти його в індексі).
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.