Git
Chapters ▾ 2nd Edition

7.2 Інструменти Git - Інтерактивне індексування

Інтерактивне індексування

У цій секції ми розглянемо декілька інтерактивних команд Git, що допомагають легко майструвати коміти, щоб вони включали тільки певні комбінації та частини файлів. Ці інструменти допомагають, коли ви редагуєте багато файлів, а потім вирішуєте, що краще записати ці зміни в декількох цілеспрямованих комітах, ніж в одному великому безладному коміті. Таким чином ви можете бути впевнені, що ваші коміти є логічно розділеними змінами та можуть бути легко перевірені програмістами, що з вами працюють. Якщо ви виконаєте git add з опцією -i або --interactive, Git перейде до інтерактивного режиму та покаже щось таке:

$ git add -i
           staged     unstaged path
  1:    unchanged        +0/-1 TODO
  2:    unchanged        +1/-1 index.html
  3:    unchanged        +5/-1 lib/simplegit.rb

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

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

Після цього йде секція команд (“Commands”), що дозволяє робити чимало всього, наприклад, індексувати та деіндексувати файли, індексувати частини файлів, додавати не супроводжувані файли та відображати проіндексовані зміни.

Індексування та деіндексування файлів

Якщо ви наберете 2 або u після запиту What now>, вас запитають, які файли ви бажаєте проіндексувати:

What now> 2
           staged     unstaged path
  1:    unchanged        +0/-1 TODO
  2:    unchanged        +1/-1 index.html
  3:    unchanged        +5/-1 lib/simplegit.rb
Update>>

Щоб проіндексувати файли TODO та index.html, ви можете набрати числа:

Update>> 1,2
           staged     unstaged path
* 1:    unchanged        +0/-1 TODO
* 2:    unchanged        +1/-1 index.html
  3:    unchanged        +5/-1 lib/simplegit.rb
Update>>

* біля кожного файла означає, що файл є вибраним для індексування. Якщо ви нічого не наберете, та натиснете Ентер після порожнього запиту Update>>, Git візьме все вибране та проіндексує його:

Update>>
updated 2 paths

*** Commands ***
  1: status     2: update      3: revert     4: add untracked
  5: patch      6: diff        7: quit       8: help
What now> 1
           staged     unstaged path
  1:        +0/-1      nothing TODO
  2:        +1/-1      nothing index.html
  3:    unchanged        +5/-1 lib/simplegit.rb

Як бачите, файли TODO та index.html проіндексовані, а файл simplegit.rb досі не проіндексований. Якщо ви тепер бажаєте деіндексувати файл TODO, ви можете використати опцію 3 або r (від revert, скасувати):

*** Commands ***
  1: status     2: update      3: revert     4: add untracked
  5: patch      6: diff        7: quit       8: help
What now> 3
           staged     unstaged path
  1:        +0/-1      nothing TODO
  2:        +1/-1      nothing index.html
  3:    unchanged        +5/-1 lib/simplegit.rb
Revert>> 1
           staged     unstaged path
* 1:        +0/-1      nothing TODO
  2:        +1/-1      nothing index.html
  3:    unchanged        +5/-1 lib/simplegit.rb
Revert>> [enter]
reverted one path

Якщо ви знову подивитесь на статус Git, то побачите, що файл TODO деіндексований:

*** Commands ***
  1: status     2: update      3: revert     4: add untracked
  5: patch      6: diff        7: quit       8: help
What now> 1
           staged     unstaged path
  1:    unchanged        +0/-1 TODO
  2:        +1/-1      nothing index.html
  3:    unchanged        +5/-1 lib/simplegit.rb

Щоб побачити зміни, які ви проіндексували, ви можете використати команди 6 або d (від diff, різниця). Вона показує список індексованих файлів, та ви можете вибрати ті, для яких бажаєте побачити індексовані зміни. Це дуже схоже на виконання git diff --cached з командного рядка:

*** Commands ***
  1: status     2: update      3: revert     4: add untracked
  5: patch      6: diff        7: quit       8: help
What now> 6
           staged     unstaged path
  1:        +1/-1      nothing index.html
Review diff>> 1
diff --git a/index.html b/index.html
index 4d07108..4335f49 100644
--- a/index.html
+++ b/index.html
@@ -16,7 +16,7 @@ Date Finder

 <p id="out">...</p>

-<div id="footer">contact : support@github.com</div>
+<div id="footer">contact : email.support@github.com</div>

 <script type="text/javascript">

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

Індексування латок (patch)

Git також може індексувати окремі частини файлів без індексування решти частин. Наприклад, якщо ви зробили дві зміни у файлі simplegit.rg, проте бажаєте проіндексувати тільки одну з них, це дуже легко зробити в Git. Наберіть 5 або p (від patch - латка) в тому ж інтерактивному запиті, про який було розказано вище. Git спитає, які файли ви бажаєте частково індексувати. Потім, для кожної секції вибраних файлів, відобразить шмати різниці файлів та запитає, чи бажаєте ви проіндексувати кожен:

diff --git a/lib/simplegit.rb b/lib/simplegit.rb
index dd5ecc4..57399e0 100644
--- a/lib/simplegit.rb
+++ b/lib/simplegit.rb
@@ -22,7 +22,7 @@ class SimpleGit
   end

   def log(treeish = 'master')
-    command("git log -n 25 #{treeish}")
+    command("git log -n 30 #{treeish}")
   end

   def blame(path)
Stage this hunk [y,n,a,d,/,j,J,g,e,?]?

Наразі у вас багато варіантів. Набравши ? ви побачите список своїх можливостей:

Stage this hunk [y,n,a,d,/,j,J,g,e,?]? ? (Проіндексувати цей шмат [y,n,a,d,/,j,J,g,e,?]? ?)
y - stage this hunk (проіндексувати цей шмат)
n - do not stage this hunk (не індексувати цей шмат)
a - stage this and all the remaining hunks in the file (індексувати цей і решту шматів у файлі)
d - do not stage this hunk nor any of the remaining hunks in the file (не індексувати ані цей шмат ані решту шматів у файлі)
g - select a hunk to go to (вибрати шмат до якого перейти)
/ - search for a hunk matching the given regex (шукати шмат за регулярним виразом)
j - leave this hunk undecided, see next undecided hunk (залишити цей шмат нерозв'язаним, перейти до наступного нерозв'язаного шмата)
J - leave this hunk undecided, see next hunk (залишити цей шмат нерозв'язаним, перейти до наступного шмата)
k - leave this hunk undecided, see previous undecided hunk (залишити цей шмат нерозв'язаним, перейти до попереднього нерозв'язаного шмата)
K - leave this hunk undecided, see previous hunk (залишити цей шмат нерозв'язаним, перейти до попереднього шмата)
s - split the current hunk into smaller hunks (подрібнити цей шмат)
e - manually edit the current hunk (редагувати поточний шмат вручну)
? - print help (надрукувати допомогу)

Зазвичай вам буде достатньо y та n, якщо ви бажаєте індексувати кожен, проте індексування всіх шматів у деяких файлах, або відтермінування рішення щодо шмату також можуть бути корисними. Якщо ви проіндексуєте одну частину файлу та залишите іншу неіндексованою, ваш статус буде виглядати так:

What now> 1
           staged     unstaged path
  1:    unchanged        +0/-1 TODO
  2:        +1/-1      nothing index.html
  3:        +1/-1        +4/-0 lib/simplegit.rb

Статус файлу simplegit.rb цікавий. Він показує, що декілька рядків індексовані, а декілька ні. Ви частково проіндексували файл. Тепер ви можете покинути скрипт інтерактивного додавання та виконати git commit щоб зберегти частково проіндексовані файли.

Вам не обов’язково бути в інтерактивному режимі додавання щоб частково проіндексувати файл — ви можете запустити той самий скрипт за допомогою git add -p або git add --patch з командного рядка.

Більш того, ви можете використовувати цей режим для часткового скидання (resetting) файлів за допомогою команди git reset --patch, отримувати частини файлів командою git checkout --patch) та заховувати частини файлів командою `git stash save --patch. Ми докладніше розглянемо кожну з них, коли дійдемо до складніших використань цих команд.