Изолировать одно изменение от другого с помощью git - PullRequest
2 голосов
/ 05 августа 2011

Я работаю в своей локальной ветке master над новой функцией, которая еще не готова к запуску в производство. Тем не менее, я только что обнаружил отдельную ошибку в своем живом приложении и быстро исправил ее локально. Тем не менее, я хочу перенести это исправление в мою удаленную главную ветку, не добавляя эту новую функцию, над которой я работал. Как я могу это сделать?

Ответы [ 6 ]

3 голосов
/ 05 августа 2011

Менее серьезный ответ:

Возвращаясь ко времени и используя подходящую модель ветвления для своей разработки.Перестаньте работать в вашей производственной ветви и начните использовать функциональные ветви.Ситуация, которую вы описываете, является именно тем, почему вы должны использовать ветки: возможность откладывать свою работу по разработке, проверять мастер, исправлять ошибки и возвращаться в свою ветку разработки.Игнорируя ветвления, вы игнорируете многое из того, что делает Git удивительным.

Более серьезный ответ:

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

Если ваша история коммитов выглядит следующим образом:

A <-- (master) bug fix, you want to push this
B <-- you don't want to push this
C <-- (origin/master)

Вы можете использовать git rebase -i HEAD~2, чтобы изменить порядокпоследние два коммита выглядят так (просто измените порядок строк в появившемся редакторе):

B <-- (master) you don't want to push this
A <-- bug fix
C <-- (origin/master)

Запишите SHA1 в B, вы собираетесь временновырежьте это из своей основной ветки.После того, как вы записали SHA1, вы можете использовать git update-ref refs/heads/master [SHA1 of A], в результате чего

A <-- (master) bug fix
C <-- (origin/master)

Теперь вы можете git push объединить A в origin/master и отправить результаты в origin.

Наконец, чтобы вернуть вашу работу по разработке (commit B), создайте новую ветку разработки (которую вы должны были сделать в первую очередь), указывая на ваш B commit: git branch development [SHA1 of B]

Ваш репозиторий теперь будет выглядеть так:

B <-- (development) you don't want to push this
A <-- (master,origin/master) bug fix
C <-- where origin/master *was* before pushing

Когда вы будете готовы к тому, чтобы эта работа по разработке была объединена с мастером, вы можете:

git checkout master
git merge development
1 голос
/ 06 августа 2011

У вас есть несколько хороших, но немного сложных ответов. Я надеюсь немного упростить это. Далее предполагается, что вы зафиксировали свое исправление только в одном коммите, последнем в вашей локальной ветке master.

git branch new-feature master~1
git checkout -b bugfix
git branch -f master origin/master
git rebase --onto master new-feature

Это помещает работу над вашей новой функцией в свою собственную ветку, называемую new-feature, помещает исправление вашей ошибки в отдельную ветку, называемую bugfix, сбрасывает вашу основную ветку, чтобы соответствовать тому, что вы в последний раз нажали, затем перезагружается, чтобы удалить новую функцию. работать из вашей ветки исправления ошибок.

Так вы обычно хотели бы, чтобы ваши ветки выглядели в этот момент. Как я это понял, пока не очень важно понимать, потому что в будущем вы просто создадите новую ветку с git checkout -b another-new-feature master, прежде чем начнете работать над другой новой функцией или исправлением ошибки.

Теперь, чтобы отправить только исправление, просто выполните:

git checkout master
git merge bugfix
git push

Затем, чтобы продолжить работу над новой функцией, выполните:

git checkout new-feature

Если вы хотите включить исправление ошибки в ветку новых функций, выполните:

git rebase master

В противном случае он будет объединен до того, как вы сделаете следующий толчок. Когда вы будете готовы выдвинуть новую функцию, просто сделайте то же самое, что и для ветви bugfix, но с веткой new-feature.

0 голосов
/ 05 августа 2011

Используйте функцию интерактивного добавления Git, чтобы добавить только исправление в «область подготовки». Затем вы можете спрятать оставшиеся изменения, проверить исправление, чтобы убедиться, что оно работает, а затем зафиксировать его самостоятельно.

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


В этом примере есть изменения как bar.c, так и foo.c, но только foo.c имеет изменения, связанные с исправлением ошибки. Во-первых, я использую git add -i для интерактивного добавления только исправления:

test(master *)$ git add -i
           staged     unstaged path
  1:    unchanged        +1/-0 bar.c
  2:    unchanged        +1/-1 foo.c

*** Commands ***
  1: status       2: update       3: revert       4: add untracked
  5: patch        6: diff         7: quit         8: help

Я выбираю опцию «p», чтобы сообщить Git, что я хочу выбрать отдельные «патчи» для добавления в «область подготовки»:

What now> p
           staged     unstaged path
  1:    unchanged        +1/-0 bar.c
  2:    unchanged        +1/-1 foo.c

Далее я набираю 2, чтобы сообщить, что я хочу выбрать отдельные патчи из foo.c:

Patch update>> 2
           staged     unstaged path
  1:    unchanged        +1/-0 bar.c
* 2:    unchanged        +1/-1 foo.c

Поскольку foo.c - единственный файл, в котором есть исправления, которые я хочу добавить в «область подготовки», теперь я закончил выбор файлов, поэтому просто нажимаю клавишу ввода в командной строке:

Patch update>>

Далее Git показывает мне отдельные патчи из "foo.c" и спрашивает, хочу ли я добавить их в индекс. В этом примере есть только одно изменение, поэтому я ставлю его:

diff --git a/foo.c b/foo.c
index 7bc741e..ec7ddfc 100644
--- a/foo.c
+++ b/foo.c
@@ -1 +1 @@
-Here is foo.c; it has a bug.
+Here is foo.c.
Stage this hunk [y,n,q,a,d,/,e,?]? y

Теперь я поставил все, что является частью исправления. Поэтому я выхожу из режима «интерактивного добавления»:

*** Commands ***
  1: status       2: update       3: revert       4: add untracked
  5: patch        6: diff         7: quit         8: help
What now> q
Bye.

Обратите внимание на статус. foo.c имеет изменения, добавленные в "область подготовки", но "bar.c" не делает:

test(master *+)$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   foo.c
#
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   bar.c
#

Затем я говорю Git, чтобы спрятать мою работу, но оставить то, что я добавил, в «область подготовки» (a.k.a. «индекс»):

test(master *+)$ git stash --keep-index
Saved working directory and index state WIP on master: ba84dec Adding bar.c with new "bar feature"
HEAD is now at ba84dec Adding bar.c with new "bar feature"
test(master +$)$ git status
# On branch master
# Changes to be committed:
#   (use "git reset HEAD <file>..." to unstage)
#
#       modified:   foo.c
#

Теперь обратите внимание, что единственное, что есть в моем рабочем дереве, это исправление, и оно готово для фиксации в следующем коммите. Теперь я могу выполнить любое тестирование, которое я хотел бы выполнить для исправления ошибки, прежде чем его зафиксировать.

Когда я удовлетворен своими изменениями, я могу зафиксировать исправление:

test(master +$)$ git commit
[master 79acd00] Commit bugfix for foo.c
 1 files changed, 1 insertions(+), 1 deletions(-)

Теперь я открываю тайник, чтобы получить другую работу, которую я делал в bar.c, обратно в мое рабочее дерево:

test(master $)$ git stash pop
# On branch master
# Changes not staged for commit:
#   (use "git add <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#       modified:   bar.c
#
no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (d306d098a272335ed31c14f07cf57e62ffc13151)

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

0 голосов
/ 05 августа 2011

Здесь - это ответ, проходящий через команды. Я написал это на похожий вопрос.

Основой этого является перемещение исправления ошибки в отдельную ветку и объединение этой ветки с вашим мастером и темой. Вместо того, чтобы исправлять изменения в шаге 4, используйте git cherry-pick bugFixSHA, затем удалите коммит из вашей функциональной ветви.

0 голосов
/ 05 августа 2011
  1. Интерактивная перебазировка и перемещение коммита с исправлением ошибки в первый коммит ревизии
  2. Создать новую ветку, указывающую на фиксацию исправления ошибки
  3. Перенесите новую ветку исправления ошибок на удаленный мастер

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

Не уверен, сработает ли ascii art:

  [origin/master]  hash_0 blah
  [new_feature  ]  hash_1 feature progress: more widgets!
                   hash_2 feature progress: less widgets, what was I thinking?
                   hash_3 bug fix: fixed memory management

Команды могут выглядеть примерно так:

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

git rebase -i origin/master

На данный момент вы получите список коммитов:

hash_1 feature progress: more widgets!
hash_2 feature progress: less widgets, what was I thinking?
hash_3 bug fix: fixed memory management

Вы переупорядочите свои коммиты:

hash_3 bug fix: fixed memory management
hash_1 feature progress: more widgets!
hash_2 feature progress: less widgets, what was I thinking?

Если вы получили здесь ошибки, то исправление вашей ошибки зависит от изменений вашей новой функции. Трудно дать совет по этому поводу. Обычно в этом случае я просто воссоздаю исправление ошибки в origin / master.

  [origin/master]  hash_0 blah
  [new_feature  ]  hash_3 bug fix: fixed memory management
                   hash_1 feature progress: more widgets!
                   hash_2 feature progress: less widgets, what was I thinking?

Мы должны быть в правильном порядке, я обычно открываю gitk и визуально проверяю, как выглядит, как я ожидаю. Вы ожидаете увидеть исправление вашей ошибки следующим коммитом после origin / master.

git checkout hash_3
git branch some_bug_fix
git push origin some_bug_fix:master
git checkout new_feature
git rebase origin/master

Последний ребаз, наверное, излишен.

  [origin/master]  hash_0 blah
                   hash_3 bug fix: fixed memory management
  [new_feature  ]  hash_1 feature progress: more widgets!
                   hash_2 feature progress: less widgets, what was I thinking?

В качестве альтернативы

  1. Оформить заказ на пульт ДУ
  2. Cherry выбирает фиксацию исправления ошибки.

Это будет дублировать код в вашей локальной ветке, так что вам нужно будет удалить его из вашей локальной ветки и перебазировать на master.

Я всегда использую gitk to cherry pick, не могу помочь с командами.

0 голосов
/ 05 августа 2011

Ну, вы можете добавить только те файлы, которые хотите зафиксировать, в область подготовки и зафиксировать их в своей ветке. Затем создайте другую ветку и зафиксируйте файлы, которые вы не хотите фиксировать. Тогда вы просто нажимаете на ветку с исправлением.

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

Если вы хотите переключить ветку, когда у вас есть незафиксированные файлы, вы можете добавить их в свою промежуточную область, получить другую ветку и затем зафиксировать свою промежуточную область в этой другой ветви.

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

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