Git: Створіть гілку з нестандартних / незапущених змін у master


991

Контекст: Я працюю над майстром, додаючи просту функцію. Через кілька хвилин я усвідомлюю, що це не так просто, і треба було б краще працювати в новій гілці.

Це завжди трапляється зі мною, і я поняття не маю, як перейти на іншу гілку і взяти всі ці невмілі зміни зі мною, залишаючи головну гілку чистою. Я вважав, git stash && git stash branch new_branchщо просто досягну цього, але ось що я отримую:

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ echo "hello!" > testing 

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git stash
Saved working directory and index state WIP on master: 4402b8c testing
HEAD is now at 4402b8c testing

~/test $ git status
# On branch master
nothing to commit (working directory clean)

~/test $ git stash branch new_branch
Switched to a new branch 'new_branch'
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (db1b9a3391a82d86c9fdd26dab095ba9b820e35b)

~/test $ git s
# On branch new_branch
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

~/test $ git checkout master
M   testing
Switched to branch 'master'

~/test $ git status
# On branch master
# Changed but not updated:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   modified:   testing
#
no changes added to commit (use "git add" and/or "git commit -a")

Чи знаєте ви, чи є якийсь спосіб цього досягти?


1
Хоча існує більш просте рішення вашої проблеми, чи могли б ви вказати, в чому результат, який ви отримуєте, відрізняється від того, що ви хотіли?
Готьє

2
виконуючи вищезазначені або відповіді внизу, незаконні зміни відбуваються як на головній, так і на новій гілці. Я хочу їх лише на новій гілці, тому я можу перевірити майстра та працювати над іншою справою, не змінюючи ці зміни
knoopx

1
дивіться мою відредаговану відповідь. Вам потрібно здійснити свої локальні зміни в новій гілці, якщо ви хочете отримати чистий майстер. Локальні зміни - це лише відмінності між поточною HEAD та вашими файлами на диску. Ці зміни в локальних файлах не є версійними, вам потрібно сказати git, щоб зберегти їх кудись, якщо ви хочете отримати їх згодом.
Готьє

Відповіді:


1207

Не потрібно зберігати.

git checkout -b new_branch_name

не торкається ваших локальних змін. Він просто створює гілку з поточної ГОЛА та встановлює туди головку. Тож я гадаю, що цього ти хочеш.

--- Редагувати, щоб пояснити результат майстра оформлення замовлення ---

Ви плутаєтесь через те, checkout masterщо не відкидає ваші зміни?

Оскільки зміни є лише локальними, git не хоче, щоб ви їх занадто легко втратили. Після зміни гілки git не замінює ваші локальні зміни. Результат вашого checkout master:

M   testing

, це означає, що ваші робочі файли не є чистими. git змінив HEAD, але не перезаписав ваші локальні файли. Ось чому ваш останній статус все ще відображає ваші локальні зміни, хоча ви ввімкнули master.

Якщо ви дійсно хочете відмовитись від місцевих змін, вам доведеться змусити оформляти замовлення -f.

git checkout master -f

Оскільки ваші зміни ніколи не були здійснені, ви їх втратите.

Спробуйте повернутися у свою філію, внесіть зміни, а потім огляньте майстра.

git checkout new_branch
git commit -a -m"edited"
git checkout master
git status

Ви повинні отримати Mповідомлення після першої каси, але потім вже не після checkout master, і не git statusповинно відображати жодних змінених файлів.

--- Редагувати, щоб очистити плутанину щодо робочого каталогу (локальних файлів) ---

У відповідь на ваш перший коментар, місцеві зміни - це просто ... ну, локальні. Git не зберігає їх автоматично, ви повинні сказати, щоб зберегти їх на потім. Якщо ви внесете зміни та не вкажете їх явно чи приховуєте, git не буде їх версіювати. Якщо ви змінили HEAD ( checkout master), локальні зміни не будуть перезаписані, оскільки вони не збережені.


32
Тут заплутаною є те, що на сторінці людини git вказується, що git checkout"Оновлення файлів у робочому дереві, щоб відповідати версії в індексі або вказаному дереву". Це передбачає, що ваші зміни у вашій файловій системі будуть GONE згодом. Без жодного шансу повернути їх. Навіть якщо ви скажете, що цього не зробите, це все одно залишає дуже погані відчуття. Я не довіряю цим взагалі . Або документація дійсно погана, або поведінка за замовчуванням git - це справді небезпечно. Не слід довіряти деяким «автоматичним» евристикам, щоб виявити, що в цьому випадку ви не хочете втрачати свої зміни.
Evi1M4chine

16
Якщо ви перевіряєте комісію, яка перезаписує ваші локальні зміни (якщо історія між поточним і цільовим комітетом стосується ваших локально модифікованих файлів), git відмовляється. Тільки якщо checkoutце не суперечить вашим місцевим змінам, замовлення працює і залишає локальні зміни в спокої. Я розумію погані почуття, хоча на сторінці man, можливо, слід сказати "Оновлення немодифікованих файлів у робочому дереві". З іншого боку, Git не надто легко втрачає локальні зміни. git checkoutабо дозволяє лише локальні зміни самостійно, або відмовляється, якщо є конфлікт.
Готьє

1
ну як я можу перейти до іншого відділення, не внісши там місцеві зміни?
ア レ ッ ク ス

5
@Alex git checkout <other_branch> -f. Ви втратите свої локальні зміни без попередження.
Готьє

2
@ Evi1M4chine Перший. Документація є дуже погано.
Qwertie

62

Спробуйте:

git stash
git checkout -b new-branch
git stash apply

6
Чи відрізняється це від того, що само робити "git checkout -b new-branch"?
Адріан Муат

Я не думаю, що це було коли перша відповідь була написана, але я можу помилитися. На жаль, через мої робочі обставини, я використовую силу протягом останніх кількох років, тому не можу зараз засвідчити її точність.
Грант Лімберг

6
Або замість останніх двох кроків: git stash branch new-branch
rethab

1
git stash більше не потрібно
kory

Коли у вас вже є відділення, куди ви хочете помістити всі свої речі, приховування має для мене сенс: (Врешті-решт, git fetch --all; отримати віддалену гілку за походженням) git stash; git checkout <існуюча галузь>; застосувати git stash;
Паолоф76

24

Дві речі, які ви можете зробити:

git checkout -b sillyname
git commit -am "silly message"
git checkout - 

або

git stash -u
git branch sillyname stash@{0}

( git checkout -<- тире - це ярлик для попередньої гілки, на якій ви були)

( git stash -u<- -uозначає, що він також приймає нестандартні зміни)


7

Якщо ви користуєтесь клієнтом GitHub Windows (як і я), і ви стикаєтесь із неспроможними змінами, які ви хочете перенести в нову гілку, ви можете просто "створити нову гілку" через клієнт GitHub. Він перейде до новоствореної філії та збереже ваші зміни.

введіть тут опис зображення


який приховує зміни перед створенням нової гілки, щоб не зберегти їх (версія 223 на Mac OS)
Фернандо Ґаллего

2

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

git checkout -b branch_name

Це створить нову гілку з вашої поточної гілки (припустивши, що вона є головним), скопіює невмінні зміни та перейде до нової гілки.

Внесіть зміни в нову гілку.

git commit -m "First commit"

Оскільки створюється нова гілка, перш ніж натиснути її на віддалений, потрібно встановити верхній потік. Використовуйте команду нижче, щоб встановити верхній потік і натиснути його на віддалений.

git push --set-upstream origin feature/feature/NEWBRANCH

Після натискання цієї команди на пульті буде створена нова гілка, а ваша нова локальна гілка буде висунута на віддалену.

Тепер, якщо ви хочете викинути свої невмілі зміни із головного відділення, скористайтеся:

git checkout master -f

Це викине будь-які неподані місцеві зміни під час оформлення замовлення.


Чим ця відповідь відрізняється від прийнятої?
куметен

Хоча є певна дублювання з прийнятою відповіддю, це забезпечує просте покрокове керівництво, а також включає операції, необхідні для віддаленого натискання нової гілки. Простий, зрозумілий і корисний.
Кяртан

Ця відповідь ясна і мені дуже допомогла.
Вадим

0

В останньому клієнті GitHub для Windows , якщо у вас залишилися зміни, виберіть нову гілку.
Це підкаже, як впоратися з цим точним сценарієм:

введіть тут опис зображення

Це ж стосується, якщо ви також просто перемикаєте гілку.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.