Можно ли разделить уже разделенный кусок с помощью git? - PullRequest
175 голосов
/ 08 июня 2011

Я недавно обнаружил в git команду patch для команды add, и я должен сказать, что это действительно фантастическая функция. Я также обнаружил, что большой кусок можно разделить на более мелкие фрагменты, нажав клавишу s , что повышает точность фиксации. Но что, если я хочу еще большей точности, если разделенный кусок не достаточно мал?

Например, рассмотрим этот разделенный кусок:

@@ -34,12 +34,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

Как добавить удаление комментариев CSS только к следующему коммиту? Опция s больше не доступна!

Ответы [ 4 ]

221 голосов
/ 09 июня 2011

Если вы используете git add -p и даже после разделения с помощью s , у вас недостаточно небольших изменений, вы можете использовать e для непосредственного редактирования патча.

Это может немного сбивать с толку, но если вы осторожно , следуйте инструкциям в окне редактора, которое откроется после нажатия e тогда ты будешь в порядке.В случае, когда вы указали, вы должны заменить - пробелом в начале этих строк:

-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {

... и удалить следующую строку, т.е.начинается с +.Если вы затем сохраните и выйдите из редактора, будет произведено только удаление комментария CSS.

50 голосов
/ 12 июня 2016

Допустим, ваш example.css выглядит так:

.classname {
  width: 440px;
}

/*#field_teacher_id {
  display: block;
} */

form.table-form #field_teacher + label,
form.table-form #field_producer_distributor + label {
  width: 300px;
}

.another {
  width: 420px;
}

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

.classname {
  width: 440px;
}

#user-register form.table-form .field-type-checkbox label {
  width: 300px;
}

.another {
  width: 420px;
}

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

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

git add --patch
diff --git a/example.css b/example.css
index 426449d..50ecff9 100644
--- a/example.css
+++ b/example.css
@@ -2,12 +2,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

Stage this hunk [y,n,q,a,d,/,e,?]?

Ой, похоже, изменения слишком близки, так что git объединил их вместе.

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

Итак, давайте вручную отредактируем , нажав e

Stage this hunk [y,n,q,a,d,/,e,?]? e

git откроет патч в нашем редакторе.

# Manual hunk edit mode -- see bottom for a quick guide
@@ -2,12 +2,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */
-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.

Давайте рассмотрим цель:

Как добавить удаление комментария CSS только к следующему коммиту?

Мы хотим разделить это на два коммита:

  1. Первый коммит включает удаление некоторых строк (удаление комментариев).

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

    -/*#field_teacher_id {
    - display: block;
    -} */

  2. Второй коммит - это изменение, которое отслеживается путем записи как удалений, так и добавлений:

    • Удаление (старые строки выбора удалены)

      Чтобы сохранить старые строки селектора (не удаляйте их во время этого коммита), мы хотим ...

      Чтобы удалить строки '-', сделайте их ''

      ... что буквально означает замену знака минус - пробелом символа.

      Итак, эти три строки ...

      -
      -form.table-form #field_teacher + label,
      -form.table-form #field_producer_distributor + label {

      ... станет ( уведомление пробел в первой из всех трех строк):


      form.table-form #field_teacher + label,
      form.table-form #field_producer_distributor + label {

    • Дополнения (добавлена ​​новая строка выбора)

      Чтобы не обращать внимания на новую строку селектора, добавленную во время этого коммита, мы хотим ...

      Чтобы удалить строки '+', удалите их.

      ... что буквально означает удаление всей строки:

      +#user-register form.table-form .field-type-checkbox label {

      (Бонус: если вы используете vim в качестве редактора, нажмите d d , чтобы удалить строку. Nano пользователи нажимают Ctrl + K )

Ваш редактор должен выглядеть следующим образом при сохранении:

# Manual hunk edit mode -- see bottom for a quick guide
@@ -2,12 +2,7 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */

 form.table-form #field_teacher + label,
 form.table-form #field_producer_distributor + label {
   width: 300px;
 }

# ---
# To remove '-' lines, make them ' ' lines (context).
# To remove '+' lines, delete them.
# Lines starting with # will be removed.
#
# If the patch applies cleanly, the edited hunk will immediately be
# marked for staging. If it does not apply cleanly, you will be given
# an opportunity to edit again. If all lines of the hunk are removed,
# then the edit is aborted and the hunk is left unchanged.

Теперь давайте сделаем коммит.

git commit -m "remove old code"

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

git show
commit 572ecbc7beecca495c8965ce54fbccabdd085112
Author: Jeff Puckett <jeff@jeffpuckett.com>
Date:   Sat Jun 11 17:06:48 2016 -0500

    remove old code

diff --git a/example.css b/example.css
index 426449d..d04c832 100644
--- a/example.css
+++ b/example.css
@@ -2,9 +2,6 @@
   width: 440px;
 }

-/*#field_teacher_id {
-  display: block;
-} */

 form.table-form #field_teacher + label,
 form.table-form #field_producer_distributor + label {

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

git add .
git commit -m "change selectors"
git show
commit 83ec3c16b73bca799e4ed525148cf303e0bd39f9
Author: Jeff Puckett <jeff@jeffpuckett.com>
Date:   Sat Jun 11 17:09:12 2016 -0500

    change selectors

diff --git a/example.css b/example.css
index d04c832..50ecff9 100644
--- a/example.css
+++ b/example.css
@@ -2,9 +2,7 @@
   width: 440px;
 }

-
-form.table-form #field_teacher + label,
-form.table-form #field_producer_distributor + label {
+#user-register form.table-form .field-type-checkbox label {
   width: 300px;
 }

Наконец, вы можете видеть, что последний коммит включает только изменения селектора.

9 голосов
/ 08 июня 2011

Если вы можете использовать git gui, это позволяет вам поэтапно вносить изменения. К сожалению, я не знаю, как это сделать из командной строки - или даже если это возможно.

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


РЕДАКТИРОВАТЬ (использование git-gui):

Я не уверен, что git-gui одинаков в версиях msysgit и linux, я использовал только msysgit. Но при условии, что это то же самое, когда вы запускаете его, есть четыре панели: верхняя левая панель - это ваш рабочий каталог, нижняя левая - ваши этапы, верхний правый - это diff для выбранного файла (будь это рабочий каталог) или в постановке), а справа внизу - описание коммита (подозреваю, что вам это не понадобится). Когда вы нажмете файл в правом верхнем углу, вы увидите diff. Если вы щелкните правой кнопкой мыши на строке различий, вы увидите контекстное меню. Следует отметить два параметра: «Стадия для фиксации» и «Строка для фиксации». Вы продолжаете выбирать «Стадия для фиксации» в строках, которые хотите зафиксировать, и все готово. Вы даже можете выбрать несколько строк и поставить их, если хотите. Вы всегда можете щелкнуть файл в промежуточном окне, чтобы увидеть, что вы собираетесь совершить.

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

1 голос
/ 08 июня 2011

Один из способов сделать это - пропустить кусок, git add, что вам еще нужно, а затем снова запустить git add. Если это единственный кусок, вы сможете разделить его.

Если вы беспокоитесь о порядке коммитов, просто используйте git rebase -i.

...