Как распилить одно большое изменение на несколько коммитов?

Создадим три файла:

george@inspiron:~/src/gitadd-p> git init
george@inspiron:~/src/gitadd-p> cal > month
george@inspiron:~/src/gitadd-p> cal -3 > 3months
george@inspiron:~/src/gitadd-p> cal -y > year
george@inspiron:~/src/gitadd-p> git add . 
george@inspiron:~/src/gitadd-p> git commit -a -m "Initial"
[master (root-commit) 6b5e406] Initial
 3 files changed, 50 insertions(+)
 create mode 100644 3months
 create mode 100644 month
 create mode 100644 year

Общий вид:

Отредактируем эти файлы:

Что покажет git diff:

george@inspiron:~/src/gitadd-p> git diff

Вот здесь приложен получившийся патч в текстовом формате.

Получится вот такая картина:

george@inspiron:~/src/gitadd-p> git status 
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   3months
        modified:   month
        modified:   year

no changes added to commit (use "git add" and/or "git commit -a")

Три файла изменены, коммитить пока ничего не прошено.

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

С первым изменением (выделением даты) всё понятно: это единствнный ханк в файле month. Добавим его, а вот git commit вызовем с ключом --verbose:

george@inspiron:~/src/gitadd-p> git add month 
george@inspiron:~/src/gitadd-p> git status          
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   month

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   3months
        modified:   year

george@inspiron:~/src/gitadd-p> git commit --verbose 

В этом состоянии git diff будет показывать только незарегистрированные изменения (в файлах 3months и year), а для просмотра застейдженных изменений надо вызывать git diff --cached (проверьте!).

Запустится текстовый редактор для написания commit message, в котором из-за --verbose для нашего удобства припишется ещё полученный diff:

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# On branch master
# Changes to be committed:
#       modified:   month
#
# Changes not staged for commit:
#       modified:   3months
#       modified:   year
#
# ------------------------ >8 ------------------------
# Do not modify or remove the line above.
# Everything below it will be ignored.
diff --git a/month b/month
index cc9c9a4..444b0c6 100644
--- a/month
+++ b/month
@@ -1,8 +1,9 @@
       Март 2019    
+
 Пн Вт Ср Чт Пт Сб Вс
              1  2  3
  4  5  6  7  8  9 10
 11 12 13 14 15 16 17
 18 19 20 21 22 23 24
-25 26 27 28 29 30 31
+25 26 27 28`29`30 31

Несмотря на множество текста, это пустой commit message! С символа "#" начинаются комментарии, а строка, содержащая «ножнички» (---- >8 ----), определяет, что все последующие строки — тоже комментарии.

Впишем commit message и закоммитим:

Mark current date

# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
#
# . . . все эти строки можно удалить, а можно не удалять,
# . . . в сообщение они не попадут

Теперь мы здесь:

george@inspiron:~/src/gitadd-p> git status          
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   3months
        modified:   year

no changes added to commit (use "git add" and/or "git commit -a")
george@inspiron:~/src/gitadd-p> git log
commit eb16f08872c152358a56683bdd5d411ef343c4e1
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 12:38:15 2019 +0300

    Mark current date

commit 6b5e40643c4e45e367b012bd867292bb74f22d78
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 11:45:32 2019 +0300

    Initial

По нашей задумке, следующий коммит должен содержать только подчёркивания — это изменения во втором и в третьем файле, причём не все. Выберем нужные ханки из всех проделанных изменений с помощью ключа --patch к команде git add:

george@inspiron:~/src/gitadd-p> git add --patch 
diff --git a/3months b/3months
index dbe1a3b..e1d398f 100644
--- a/3months
+++ b/3months
@@ -1,4 +1,5 @@
     Февраль 2019            Март 2019            Апрель 2019    
+----------------------------------------------------------------    
 Пн Вт Ср Чт Пт Сб Вс  Пн Вт Ср Чт Пт Сб Вс  Пн Вт Ср Чт Пт Сб Вс
              1  2  3               1  2  3   1  2  3  4  5  6  7
  4  5  6  7  8  9 10   4  5  6  7  8  9 10   8  9 10 11 12 13 14
Stage this hunk [y,n,q,a,d,e,?]?

Git показывает на первый попавшийся ханк и спрашивает, что с ним делать? А что можно-то?

Stage this hunk [y,n,q,a,d,e,?]? ?
y - stage this hunk
n - do not stage this hunk
q - quit; do not stage this hunk or any of the remaining ones
a - stage this hunk and all later hunks in the file
d - do not stage this hunk or any of the later hunks in the file
e - manually edit the current hunk
? - print help
@@ -1,4 +1,5 @@
     Февраль 2019            Март 2019            Апрель 2019    
+----------------------------------------------------------------    
 Пн Вт Ср Чт Пт Сб Вс  Пн Вт Ср Чт Пт Сб Вс  Пн Вт Ср Чт Пт Сб Вс
              1  2  3               1  2  3   1  2  3  4  5  6  7
  4  5  6  7  8  9 10   4  5  6  7  8  9 10   8  9 10 11 12 13 14
Stage this hunk [y,n,q,a,d,e,?]?

Нажимаем "y", смотрим два оставшихся ханка, на одном из них нажимаем "y" (это тоже подчёркивание), на другом — "n":

diff --git a/3months b/3months
index dbe1a3b..e1d398f 100644
--- a/3months
+++ b/3months
@@ -1,4 +1,5 @@
     Февраль 2019            Март 2019            Апрель 2019    
+----------------------------------------------------------------    
 Пн Вт Ср Чт Пт Сб Вс  Пн Вт Ср Чт Пт Сб Вс  Пн Вт Ср Чт Пт Сб Вс
              1  2  3               1  2  3   1  2  3  4  5  6  7
  4  5  6  7  8  9 10   4  5  6  7  8  9 10   8  9 10 11 12 13 14
Stage this hunk [y,n,q,a,d,e,?]? y
<stdin>:7: trailing whitespace.
----------------------------------------------------------------    
warning: 1 line adds whitespace errors.

diff --git a/year b/year
index 1b02bfa..1c0b8be 100644
--- a/year
+++ b/year
@@ -1,4 +1,5 @@
                                2019                               
+------------------------------------------------------------------
 
        Январь                 Февраль                 Март        
 Пн Вт Ср Чт Пт Сб Вс   Пн Вт Ср Чт Пт Сб Вс   Пн Вт Ср Чт Пт Сб Вс
Stage this hunk [y,n,q,a,d,j,J,g,/,e,?]? y
@@ -16,14 +17,25 @@
 22 23 24 25 26 27 28   20 21 22 23 24 25 26   17 18 19 20 21 22 23
 29 30                  27 28 29 30 31         24 25 26 27 28 29 30
                                                                   
-        Июль                  Август                Сентябрь      
-Пн Вт Ср Чт Пт Сб Вс   Пн Вт Ср Чт Пт Сб Вс   Пн Вт Ср Чт Пт Сб Вс
- 1  2  3  4  5  6  7             1  2  3  4                      1
- 8  9 10 11 12 13 14    5  6  7  8  9 10 11    2  3  4  5  6  7  8
-15 16 17 18 19 20 21   12 13 14 15 16 17 18    9 10 11 12 13 14 15
-22 23 24 25 26 27 28   19 20 21 22 23 24 25   16 17 18 19 20 21 22
-29 30 31               26 27 28 29 30 31      23 24 25 26 27 28 29
-                                              30                  
+        Июль                  Август          
+Пн Вт Ср Чт Пт Сб Вс   Пн Вт Ср Чт Пт Сб Вс   
+ 1  2  3  4  5  6  7             1  2  3  4   
+ 8  9 10 11 12 13 14    5  6  7  8  9 10 11   
+15 16 17 18 19 20 21   12 13 14 15 16 17 18   
+22 23 24 25 26 27 28   19 20 21 22 23 24 25   
+29 30 31               26 27 28 29 30 31      
+                                              
+Осень!
+
+      Сентябрь      
+Пн Вт Ср Чт Пт Сб Вс
+                   1
+ 2  3  4  5  6  7  8
+ 9 10 11 12 13 14 15
+16 17 18 19 20 21 22
+23 24 25 26 27 28 29
+30                  
+
        Октябрь                Ноябрь                 Декабрь      
 Пн Вт Ср Чт Пт Сб Вс   Пн Вт Ср Чт Пт Сб Вс   Пн Вт Ср Чт Пт Сб Вс
     1  2  3  4  5  6                1  2  3                      1
Stage this hunk [y,n,q,a,d,K,g,/,e,?]? n

Получаем такую ситуацию: для year есть застейжденные (поставленные в коммит) и незастейдженные изменения одновременно:

george@inspiron:~/src/gitadd-p> git status 
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)

        modified:   3months
        modified:   year

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   year

Посмотрим уже поставленные в коммит изменения:

george@inspiron:~/src/gitadd-p> git diff --cached | cat
diff --git a/3months b/3months
index dbe1a3b..e1d398f 100644
--- a/3months
+++ b/3months
@@ -1,4 +1,5 @@
     Февраль 2019            Март 2019            Апрель 2019    
+----------------------------------------------------------------    
 Пн Вт Ср Чт Пт Сб Вс  Пн Вт Ср Чт Пт Сб Вс  Пн Вт Ср Чт Пт Сб Вс
              1  2  3               1  2  3   1  2  3  4  5  6  7
  4  5  6  7  8  9 10   4  5  6  7  8  9 10   8  9 10 11 12 13 14
diff --git a/year b/year
index 1b02bfa..ffc8dc1 100644
--- a/year
+++ b/year
@@ -1,4 +1,5 @@
                                2019                               
+------------------------------------------------------------------
 
        Январь                 Февраль                 Март        
 Пн Вт Ср Чт Пт Сб Вс   Пн Вт Ср Чт Пт Сб Вс   Пн Вт Ср Чт Пт Сб Вс

Закоммитим их по-быстрому, а затем и всё, что осталось (ключ -m позволяет задать commit message из командной строки, а -a — автоматически (без git add) добавить в коммит изменённые файлы:

george@inspiron:~/src/gitadd-p> git commit -m "Underscores"
[master ad8856b] Underscores
 2 files changed, 2 insertions(+)
george@inspiron:~/src/gitadd-p> git status 
On branch master
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

        modified:   year

no changes added to commit (use "git add" and/or "git commit -a")
george@inspiron:~/src/gitadd-p> git commit -a -m 'Announcing Autumn!'
[master a218c80] Announcing Autumn!
 1 file changed, 19 insertions(+), 8 deletions(-)
george@inspiron:~/src/gitadd-p> git status 
On branch master
nothing to commit, working tree clean

Вот два способа просмотреть историю:

george@inspiron:~/src/gitadd-p> git log
commit a218c80232a112bfe91a001deac87b8eb0b1a6a4
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 13:04:09 2019 +0300

    Announcing Autumn!

commit ad8856b667beb386e131403559f55d42627c95bf
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 13:03:37 2019 +0300

    Underscores

commit eb16f08872c152358a56683bdd5d411ef343c4e1
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 12:38:15 2019 +0300

    Mark current date

commit 6b5e40643c4e45e367b012bd867292bb74f22d78
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 11:45:32 2019 +0300

    Initial

Второй включает в себя сводку по изменениям:

george@inspiron:~/src/gitadd-p> git log --status
commit a218c80232a112bfe91a001deac87b8eb0b1a6a4
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 13:04:09 2019 +0300

    Announcing Autumn!

 year | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

commit ad8856b667beb386e131403559f55d42627c95bf
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 13:03:37 2019 +0300

    Underscores

 3months | 1 +
 year    | 1 +
 2 files changed, 2 insertions(+)

commit eb16f08872c152358a56683bdd5d411ef343c4e1
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 12:38:15 2019 +0300

    Mark current date

 month | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

commit 6b5e40643c4e45e367b012bd867292bb74f22d78
Author: George V. Kouryachy (Fr. Br. George) <george@altlinux.ru>
Date:   Fri Mar 29 11:45:32 2019 +0300

    Initial

 3months |  8 ++++++++
 month   |  8 ++++++++
 year    | 34 ++++++++++++++++++++++++++++++++++
 3 files changed, 50 insertions(+)

Наконец, git log --patch позволит посмотреть также и diff-ы этих изменений.

FrBrGeorge/Using git add -p (последним исправлял пользователь FrBrGeorge 2024-03-12 13:12:09)