Запропонувати правкуПокращити цю статтюДопрацюйте відповідь до «Що таке git stash і коли його використовувати?». Ваші зміни проходять модерацію перед публікацією.Потрібне підтвердженняКонтентЩо ви змінюєте🇺🇸EN🇺🇦UAПереглядЗаголовок (UA)Коротка відповідь (UA)**git stash** зберігає staged і unstaged зміни в стек і очищує робоче дерево, щоб можна було переключити гілки або зробити pull без втрати роботи. `git stash pop` повертає зміни назад. Прапор `-u` включає untracked файли. **Ключове:** `pop` застосовує і видаляє запис; `apply` тільки застосовує.Показується над повною відповіддю для швидкого нагадування.Відповідь (UA)Зображення**git stash** тимчасово зберігає незакомічені зміни з робочого дерева і індексу в стек, очищує робоче дерево до стану поточного коміту і дозволяє застосувати їх пізніше. ## Теорія ### Коротко - Уявіть папку для чернеток: записки складаєш туди, стіл чистий для термінової задачі, потім дістаєш записки і все на своєму місці - Зберігає і staged, і unstaged зміни однією командою; додай `-u` щоб захопити і untracked файли - Базовий цикл: stash, переключитись або зробити pull, pop - `pop` застосовує stash і видаляє його зі стека; `apply` тільки застосовує, запис залишається - Коли незакомічені зміни заважають тобі перейти або зробити pull - stash. Якщо зміни вже стабільні - просто закомітти. ### Швидкий приклад ```bash # На гілці feature з незакоміченими змінами git stash push -m "WIP: валідація форми входу" # Output: Saved working directory and index state WIP: валідація форми входу git status # On branch feature, nothing to commit, working tree clean git stash pop # Відновлює все як було # Output: Dropped refs/stash@{0} ``` От і весь патерн. Stash очищує дерево, ти робиш що потрібно, pop повертає все назад. ### Коли використовувати Stash добре підходить для кількох конкретних ситуацій: - Посеред фічі прилетіло термінове виправлення: stash на feature-гілці, переходиш на main, фіксиш і комітиш, повертаєшся, pop - Незакомічені зміни блокують `git pull`: stash, pull, pop (конфлікти вирішуєш після, якщо з'являться) - Переключення надто швидке для нормального коміту: stash з описовим повідомленням замість напівготового коміту з "WIP" у назві Не варто використовувати stash якщо очікуєш конфлікти при застосуванні - краще створи гілку. І якщо зміни вже стабільні - просто закомітти. ### Як git stash працює всередині Git створює два коміти під капотом. Перший фіксує стан індексу (staged файли) як дерево. Другий фіксує diff робочого дерева поверх нього. Обидва зберігаються в `.git/refs/stash` як reflog-стек, де `stash@{0}` завжди найновіший запис. `git stash push` викликає `git commit-tree` для збереження цих станів, потім скидає HEAD, індекс і робоче дерево до базового коміту. `git stash pop` відтворює diff і прибирає запис з reflog якщо немає конфліктів. Саме тому виникають конфлікти при pop: збережений diff створювався відносно одного базового коміту, але до моменту pop база могла змінитись. ### Типові помилки **Забути `-u` при наявності untracked файлів:** ```bash npm install new-dep # Створює untracked файли git stash # Ігнорує їх за замовчуванням git checkout other # Ці файли залишаються або зникають в дивний спосіб ``` Виправлення: `git stash -u`. Або переконайся що `.gitignore` покриває те що не потрібно відстежувати. Stash, потім `git pull --rebase` без pop: ```bash git stash git pull --rebase origin main # Переписує базовий коміт git stash pop # Stash створювався на старій базі, конфлікти майже гарантовані ``` Stash зберігає diff відносно базового коміту на момент збереження. Після rebase база змінилась. Pop перед rebase, або rebase спочатку і pop після. **Припускати що `pop` завжди чисто прибирає запис при конфлікті:** ```bash git stash pop # CONFLICT (content): Merge conflict in file.js # Applying stash failed, stash remains ``` Коли pop натрапляє на конфлікт, він застосовує зміни з маркерами але НЕ видаляє запис зі стека. Безпечніший шлях: `git stash apply`, вирішити конфлікти вручну, потім `git stash drop`. Видалення не того stash за індексом: ```bash git stash list # stash@{0}: WIP: нова фіча # stash@{1}: WIP: старий експеримент git stash drop stash@{1} # Індекси зміщуються при кожному push або pop ``` Завжди запускай `git stash list` безпосередньо перед видаленням. Якщо записів багато, `git stash branch new-branch stash@{0}` надійніший ніж жонглювання індексами. ### Де зустрічається в реальних проектах - Контрибʼютори React stash-ають незакінчені зміни перед `git pull upstream` щоб merge залишався чистим (описано в CONTRIBUTING.md) - Контрибʼютори Node.js stash-ають незакомічені бенчмарки під час pull коли прилітають CI-фікси - Розробники розширень VS Code stash-ають часткові TypeScript зміни між переключеннями гілок - `git stash` проти `git worktree`: stash для швидких переключень контексту; worktree краще коли потрібні дві гілки відкриті паралельно і надовго ### Питання на співбесіді **Q:** Яка різниця між `git stash apply` і `git stash pop`? **A:** `apply` застосовує stash але залишає його в стеку. `pop` застосовує і видаляє. Використовуй `apply` коли не впевнений що застосування пройде без конфліктів - так залишається запасний варіант. **Q:** Як git stash обробляє untracked файли? **A:** За замовчуванням ігнорує їх. Прапор `-u` або `--include-untracked` включає untracked файли. Прапор `-a` або `--all` включає ще й файли з `.gitignore`. **Q:** Що відбувається якщо `git stash pop` натрапляє на конфлікт? **A:** Git залишає маркери конфліктів у файлах, а запис залишається в стеку. Pop видаляє запис тільки при чистому застосуванні. Вирішуєш конфлікти, робиш stage файлів, потім `git stash drop`. **Q:** Чи можна stash-ати під час rebase або merge-конфлікту? **A:** Під час активного merge-конфлікту `git stash` завершиться з помилкою. Використовуй `git stash branch new-branch stash@{0}` щоб створити гілку зі стану stash замість прямого застосування. **Q:** Як stash зберігається всередині? Поясни граф комітів. **A:** Два коміти: один для стану індексу (`i`), другий для diff робочого дерева поверх нього (`w`). Обидва вказують на HEAD на момент stash. Reflog у `.git/logs/refs/stash` веде стек. `stash@{0}` вказує на `w`, батько `w` - це `i`, батько `i` - оригінальний HEAD. **Q:** Який найбезпечніший підхід коли `git stash pop` постійно конфліктує? **A:** `git stash branch new-branch stash@{0}` - створює гілку точно в тому коміті де був зроблений stash, застосовує його там (без розбіжності баз) і видаляє якщо все чисто. Потім merge або rebase цю гілку звичайним способом. ## Приклади ### Переключення гілок посеред фічі Редагуєш `Login.jsx` і stage-ив зміни утиліт, коли прилітає проблема у продакшені. ```bash # Staged утиліти, unstaged зміни Login.jsx git stash push -u -m "WIP: валідація форми входу" # -u захоплює і untracked конфіг-файли git checkout main git checkout -b hotfix/auth-token git commit -m "Fix: протермінований токен не очищував сесію" git push origin hotfix/auth-token git checkout feature/user-auth git stash pop # Login.jsx і утиліти відновились точно як були ``` Якщо після pop з'явиться конфлікт, Git позначить файл маркерами `<<<<<<<`. Вирішуєш вручну, робиш stage, потім `git stash drop`. ### Конфлікт stash після змін в upstream Це спрацьовує навіть у досвідчених. Staged файл A, unstaged файл B, untracked файл C. Хтось пушить зміну в B поки твій stash лежить у стеку. ```bash echo "A" > A.txt && git add A.txt echo "B" > B.txt echo "C" > C.txt # untracked git stash push -u -m "часткова робота" # Тим часом на remote: B.txt отримує новий коміт git pull git stash pop # CONFLICT (content): Merge conflict in B.txt # Applying stash failed, stash remains # НЕ запускай git stash drop ще # Вирішуєш B.txt вручну, потім: git add B.txt git stash drop # Тепер безпечно ``` A.txt і C.txt відновились чисто. Конфлікт тільки по B.txt, бо і remote коміт, і stash торкались цього файлу. Бачив як розробники панікують від "stash remains" думаючи що дані втрачені - нічого не втрачено, Git просто чекає вирішення конфлікту перед очищенням. ### Правильний порядок: stash і rebase ```bash # Неправильний порядок git stash git pull --rebase origin main # База переміщується без твоїх змін git stash pop # Stash тепер вказує на стару базу, конфлікти майже гарантовані # Правильний порядок git stash git fetch origin git rebase origin/main # Спочатку rebase git stash pop # Pop на нову базу ``` Stash зберігає diff відносно базового коміту на момент збереження. Rebase переміщує цю базу. Дотримуйся правильного порядку і більшість stash-проблем зникнуть самі.Для рев’юераПримітка для модератора (необов’язково)Бачить лише модератор. Прискорює рев’ю.