it-roy-ru.com

Можно ли разделить уже разделенный кусок с помощью git?

Недавно я обнаружил опцию 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 больше не доступна!

170
greg0ire

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

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

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

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

215
Mark Longair

Допустим, ваш 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 в качестве редактора, нажмите dd удалить строку. 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 <[email protected]>
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 <[email protected]>
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;
 }

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

49
Jeff Puckett

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

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


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

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

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

9
vhallac

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

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

1
Abizern