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: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now>

Може да видите, че тази команда показва съвсем различен изглед на индексната ви област — в общи линии получавате резултатите от git status, но по един по-кратък и информативен начин. Тя извежда промените, които сте индексирали отляво, както и неиндексираните отдясно.

След това идва “Commands” секцията, която ви позволява множество действия като индексиране и деиндексиране на файлове, индексиране на част от файлове, добавяне на нови файлове и показване на diffs на индексираните данни.

Добавяне и изваждане от индекса

Ако въведете u или 2 (за обновяване) в промпта What now>, ще бъдете запитани кои файлове искате да вкарате в индексната област:

What now> u
           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>>

Символът * до всеки от файловете сега индикира, че съответния файл е избран за индексиране. Ако сега натиснете Enter в промпта Update>> без да въвеждате друго, Git взема всички избрани файлове и ги вкарва в индекса:

Update>>
updated 2 paths

*** Commands ***
  1: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now> s
           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 избирайки опцията r или 3 (за revert):

*** Commands ***
  1: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now> r
           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 status, може да видите, че TODO вече е извън индекса:

*** Commands ***
  1: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now> s
           staged     unstaged path
  1:    unchanged        +0/-1 TODO
  2:        +1/-1      nothing index.html
  3:    unchanged        +5/-1 lib/simplegit.rb

Ако искате diff на индексираното, използвайте командата d или 6 (за diff). Тя показва списък на индексираните файлове и може да изберете тези, за които искате да видите индексирания diff. Това е съвсем същото като да изпълните git diff --cached в нормалния команден ред:

*** Commands ***
  1: [s]tatus     2: [u]pdate      3: [r]evert     4: [a]dd untracked
  5: [p]atch      6: [d]iff        7: [q]uit       8: [h]elp
What now> d
           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">

С тези основни команди може да улесните работата си с индексната област.

Индексиране на пачове

Също така може да вкарате в индекса само определени части от файлове, вместо всички промени. Например, ако сте направили две промени във файла simplegit.rb, но искате да индексирате само едната, можете да го направите лесно с Git. От същия интерактивен промпт, въведете p или 5 (за patch). Git ще ви попита кои файлове искате да индексирате частично. След това, за всяка секция от избраните файлове, ще ви бъдат показани големи парчета diff информация от всеки файл (hunks) и ще бъдете попитани дали искате да ги индексирате, едно по едно:

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 - индексира текущото парче код (hunk)
n - пропуска този hunk
a - индексира този и всички останали hunks от файла
d - отменя индексирането на този и всички останали hunks от файла
g - избор на hunk към който да се премине
/ - търсене на hunk по регулярен израз (regex)
j - оставя текущия hunk без решение, показва следващия нерешен hunk
J - оставя текущия hunk без решение, показва следващия hunk
k - оставя текущия hunk без решение, показва предишния нерешен hunk
K - оставя текущия hunk без решение, показва предишния hunk
s - разделя текущия hunk на по-малки части
e - ръчна редакция на текущия hunk
? - показва помощната информация

Обикновено, ще избирате опциите y или n, ако искате да индексирате всеки hunk, но индексирането им наведнъж в определени файлове или отлагането на решението за даден hunk за по-късно, също може да е полезно. Ако индексирате една част от файл и оставите друга извън индекса, статуса може да изглежда така:

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 от командния ред.

Освен това, можете да използвате patch режима за частично възстановяване на файлове с командата git reset --patch, за изваждане в работната област на част от файлове с git checkout --patch, а също и за stashing на части от файлове с git stash save --patch. Ще видим повече подробности за тези команди по-натам в книгата.