Чи можу я розділити вже розщеплену луску за допомогою git?


204

Нещодавно я відкрив patchдля addкоманди команду git , і мушу сказати, що це дійсно фантастична особливість. Я також виявив, що велику частину можна розділити на менші хунки, натиснувши на 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Опція більше не доступна!

Відповіді:


253

Якщо ви користуєтесь, git add -pі навіть після розщеплення з ними s, ви не маєте достатньо малої зміни, ви можете eбезпосередньо редагувати виправлення.

Це може бути трохи заплутано, але якщо ви уважно дотримуєтесь інструкцій у вікні редактора, яке буде відкрито після натискання, eто ви будете добре. У випадку, яке ви цитували, ви хочете замінити -пробіл на початку цих рядків:

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

... і видаліть наступний рядок, тобто той, що починається з +. Якщо потім зберегти та вийти з редактора, буде видалено коментар CSS.


9
Класне рішення! Я бачив це, але неправильно зрозумів ... Я хоч зміни також буде видалений із робочого дерева.
greg0ire

7
Дійсно, це не дуже очевидно з тексту довідки. Насправді я дуже часто використовую це, оскільки я думаю, що git насправді спонукає вас зробити кожен
вчинок

27
Зауважте, що вам дійсно доведеться замінити його пробілом . Я спробував це, вважаючи, що я можу просто видалити -символи, і Гіт поскаржився, що мій патч не застосовується.
Райан Лунді

3
Я здогадуюсь, що причина, коли ви видаляєте рядки з '-' і замінюєте '+' пробілом, полягає в тому, що тоді ви формуєте патч, де ці рядки з '-' вже видалено, а рядки з ' + 's вже додані (в око патча). Або іншим способом дивитися на це, чи ти насправді робиш дію, яку представляють ці символи (-, +) (додавання рядка або видалення). Тільки решта рядків з '-і та' + 'записуються як зміни, а решта - "як саме файл".
atomictom

3
@Filype: Я не знаю, чому це сталося б, я боюся - якби ти працював git add -pі редагував лунку, eце повинно впливати лише на те, що ставиться, а не на твоє робоче дерево.
Марк Лонгейр

60

Скажімо, ваш 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 {

      ... стане ( помітьте єдиний пробіл у першому з усіх 3 рядків):


      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 <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;
 }

Нарешті ви бачите, що остання фіксація включає лише зміни селектора.


1
Бонус №2: Якщо ви використовуєте VIM в якості редактора, вам потрібно двічі натиснути "d" на клавіатурі, щоб видалити рядок: D
Alexxus

3
Крім того, замість видалення доданих рядків, які ви не хочете додавати, ви можете замінити +їх #. Результат такий же, але, можливо, вам незручно видаляти (і не можете повернутись) або хочете експериментувати перед тим, як зберегти.
ob-ivan

І це, бо vim r #перевищує плюс xD
aksh1618

Мета - "Як я можу додати видалення коментарів CSS лише до наступного виконання?", Але дії дійсно заплутані щодо того, що він виконує. (ми хочемо "додати" лише "видалення" кількох рядків до наступного комітету.) Так що просто сказати видалити або додати - дуже заплутано. Визначення того, що було досягнуто на кожному кроці, допоможе з’ясувати.
ahnbizcad

9

Якщо ви можете використовувати git gui, це дозволяє поетапно змінювати зміни за рядком. На жаль, я не знаю, як це зробити з командного рядка - або навіть якщо це можливо.

Ще один варіант, який я використовував у минулому, - це скасування частини змін (тримати редактор відкритим), виконувати потрібні біти, скасувати та повторно зберегти з редактора. Не дуже елегантний, але виконує роботу. :)


EDIT (використання git-gui):

Я не впевнений, чи git-gui однаковий у версіях msysgit та linux, я використовував лише msysgit. Але якщо припустити, що це так само, коли ви запускаєте його, є чотири області: у верхній лівій панелі змінюється ваш робочий каталог, внизу ліворуч змінюються ваші етапи, верхній правий - різниця для вибраного файлу (будь він працює dir або поетапно), а внизу справа - це опис виконання (я підозрюю, що він вам не знадобиться). Коли ви клацнете файл у правому верхньому куті, ви побачите розл. Якщо ви клацніть правою кнопкою миші на різну лінію, ви побачите контекстне меню. Два варіанти, які слід зауважити, - це "ступінчастість для виконання" та "сценічна лінія для фіксації". Ви продовжуєте вибирати "етапну лінію для фіксації" на рядках, які ви хочете зробити, і ви закінчили. Ви навіть можете вибрати кілька рядків і поставити їх, якщо хочете.

Щодо вчинення, ви можете використовувати або інструмент gui, або командний рядок.


Ваша друга пропозиція цілком очевидна, але перша цікава, ви могли б деталізувати трохи більше? Я встановив, git-guiале не маю поняття, як досягти того, що ви описуєте.
greg0ire

багато танків! Це працює! Мені навіть вдалося обрати рядки, які я хотів поставити, та проіндексувати їх одним клацанням миші.
greg0ire

0

Один із способів зробити це - пропустити шматок, git addвсе , що вам потрібно, а потім запустити git addзнову. Якщо це єдиний фрагмент, ви зможете розділити його.

Якщо ви турбуєтесь про порядок комісій, просто скористайтеся git rebase -i.


Це те, що я спробував, і голова в моєму питанні є єдиним, коли я git add -pзнову забігаю, але не можу розділити його. Я отримую це: Stage this hunk [y,n,q,a,d,/,e,?]?а потім натискання 's' друкує допомогу. До речі, ти мав на увазі add patch, чи не так patch add? Або є git patchплагін, який я повинен встановити?
greg0ire

Ви чинили поетапні хунки перед тим, як знову запустити це? І ні, у Mercurial є плагіни, Git - ні.
Абізерн

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

Як сказала моя відповідь → git rebase -i. Що гнучкіше ніжcommit --amend
Abizern
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.