Git создать новый коммит с подмножеством файлов в существующем коммите - PullRequest
0 голосов
/ 26 октября 2019

Иногда мне нужно разбить коммит, который касается нескольких файлов, на отдельные коммиты.

Например, предположим, у меня есть коммит, который касается файлов foo и bar, и я хочу разделить на два коммитаодин из которых касается только foo, а другой - только bar. Предположим, что коммит, который я пытаюсь разделить, является коммитом-подсказкой.

Например, предположим, что это история моего репозитория

commit a78143999ebc8fb1d696832ed5ef2654a3325bb4
Author: Gregory Nisbet <>
Date:   Fri Oct 25 23:12:55 2019 -0700

    add both foo and bar

commit 760208789956815d471ccd1ce9b642b32299cbb3
Author: Gregory Nisbet <>
Date:   Fri Oct 25 23:12:25 2019 -0700

    empty foo and bar

И я хочу изменить его на что-то более похожееэто. Там, где я добавляю новый коммит сверху, это касается только foo. Второй коммит, в этом конкретном примере, касается только bar. В идеале я хотел бы иметь возможность выполнять такое разделение, просто нацелив исходный коммит с помощью foo и bar и указав пути для добавления нового коммита.

commit 938b52c57511f1150ca0f1958458ece069205631
Author: Gregory Nisbet <>
Date:   Fri Oct 25 23:18:14 2019 -0700

    add foo only

commit d9c09b249f105ffd65f35392b26ac6a08f7effc2
Author: Gregory Nisbet <>
Date:   Fri Oct 25 23:12:55 2019 -0700

    add bar only

commit 760208789956815d471ccd1ce9b642b32299cbb3
Author: Gregory Nisbet <>
Date:   Fri Oct 25 23:12:25 2019 -0700

    empty foo and bar

Я пытался написатьскрипт, который выполняет это поведение расщепления путем создания двух возвратов и внесения поправок первого возврата в исходный коммит.

Скрипт отвратителен, но он работает в тех немногих случаях, которые я пробовал, и имеет правильный API.

Мне кажется, что должен быть более прямой способ достижения того, что я пытаюсь сделать.

#!/bin/bash


while getopts "m:" opt; do
    case "$opt" in
        m)
            message="$OPTARG" ;;
    esac
done

shift "$((OPTIND-1))"


if test -z "$message"; then
    1>&2 printf '%s\n' 'message cannot be empty'
    exit 20
fi

branch="$(python -c 'import uuid; print(str(uuid.uuid4()))')"

if 1>/dev/null 2>/dev/null git diff --exit-code; then
    : "do nothing"
else
    1>&2 printf '%s\n' 'working directory not clear'
    exit 30
fi
hash="$(git rev-parse --verify HEAD)"
# revert initial commit, write revert to index
git revert --no-commit -- "$hash" || exit 10
# remove paths specified on command line from index
git reset HEAD "$@" || { git revert --abort; exit 20; }
git checkout -- "$@" || { git revert --abort; exit 30; }
# commit partial revert
git commit --allow-empty-message --no-edit || exit 40
# revert the just-committed partial revert, keep
# the new double revert in the index
git revert --no-commit HEAD || exit 50
# checkout an unused branch
git checkout -b "$branch" || exit 60
# commit double revert
git commit --allow-empty-message --no-edit || exit 70
# go back to previous branch
git checkout - || exit 80
# uncommit the latest change (the first revert)
git reset --soft HEAD^ || exit 90
# amend first revert onto previous commit
git commit --amend --no-edit || exit 10
# go to scratch branch
git checkout "$branch" || exit 20
# revert latest change in scratch branch, keep it in the index
git reset --soft HEAD^ || exit 30
# go to previous branch
git checkout - || exit 40
# use our commit message to create a new commit with that message
git commit --no-edit --message="$message" || exit 50
# delete temporary branch
git branch -D "$branch" || exit 60

Используя приведенный выше сценарий, я могу настроить таргетинг только на подмножествопутей в коммите tip, используя gitsplit -m 'second commit' foo.

$ git init                                                                                                                                                                                                                                                  
Initialized empty Git repository in /tmp/gitdir/.git/                                                                                                                                                                                                                                        

$ echo foo > foo                                                                                                                                                                                                                                            

$ echo bar > bar                                                                                                                                                                                                                                            

$ git add foo bar                                                                                                                                                                                                                                           

$ git commit -m 'initial commit'                                                                                                                                                                                                                            
[master (root-commit) 4472c3c] initial commit                                                                                                                                                                                                                                                
 2 files changed, 2 insertions(+)                                                                                                                                                                                                                                                            
 create mode 100644 bar                                                                                                                                                                                                                                                                      
 create mode 100644 foo                                                                                                                                                                                                                                                                      

$ gitsplit -m 'second commit' foo                                                                                                                                                                                                                           
Unstaged changes after reset:                                                                                                                                                                                                                                                                
D       foo                                                                                                                                                                                                                                                                                  
[master 9a5d357] Revert "initial commit"                                                                                                                                                                                                                                                     
 1 file changed, 1 deletion(-)                                                                                                                                                                                                                                                               
 delete mode 100644 bar                                                                                                                                                                                                                                                                      
A       bar                                                                                                                                                                                                                                                                                  
Switched to a new branch 'b70d1c24-aca5-4676-a287-d35dbe14f790'                                                                                                                                                                                                                              
[b70d1c24-aca5-4676-a287-d35dbe14f790 abb559a]                                                                                                                                                                                                                                               
 1 file changed, 1 insertion(+)                                                                                                                                                                                                                                                              
 create mode 100644 bar                                                                                                                                                                                                                                                                      
Switched to branch 'master'                                                                                                                                                                                                                                                                  
[master 5d95965] initial commit                                                                                                                                                                                                                                                              
 Date: Fri Oct 25 23:36:26 2019 -0700                                                                                                                                                                                                                                                        
 1 file changed, 1 insertion(+)                                                                                                                                                                                                                                                              
 create mode 100644 foo                                                                                                                                                                                                                                                                      
Switched to branch 'b70d1c24-aca5-4676-a287-d35dbe14f790'                                                                                                                                                                                                                                    
A       bar                                                                                                                                                                                                                                                                                  
Switched to branch 'master'                                                                                                                                                                                                                                                                  
[master 2f64de7] second commit                                                                                                                                                                                                                                                               
 1 file changed, 1 insertion(+)                                                                                                                                                                                                                                                              
 create mode 100644 bar                                                                                                                                                                                                                                                                      
Deleted branch b70d1c24-aca5-4676-a287-d35dbe14f790 (was 9a5d357).                                                                                                                                                                                                                           


$ git --no-pager show --format=short HEAD                                                                                                                                                                                                                   
commit 2f64de7dc9df58323db21b676251df27c46b924f                                                                                                                                                                                                                                              
Author: Gregory Nisbet <>                                                                                                                                                                                                                                            

    second commit                                                                                                                                                                                                                                                                            

diff --git a/bar b/bar                                                                                                                                                                                                                                                                       
new file mode 100644                                                                                                                                                                                                                                                                         
index 0000000..5716ca5                                                                                                                                                                                                                                                                       
--- /dev/null                                                                                                                                                                                                                                                                                
+++ b/bar                                                                                                                                                                                                                                                                                    
@@ -0,0 +1 @@                                                                                                                                                                                                                                                                                
+bar                                                                                                                                                                                                                                                                                         

$ git --no-pager show --format=short HEAD^                                                                                                                                                                                                                  
commit 5d9596507023a4af4dd7536e49e97359b35632d6                                                                                                                                                                                                                                              
Author: Gregory Nisbet <>                                                                                                                                                                                                                                            

    initial commit                                                                                                                                                                                                                                                                           

diff --git a/foo b/foo                                                                                                                                                                                                                                                                       
new file mode 100644                                                                                                                                                                                                                                                                         
index 0000000..257cc56                                                                                                                                                                                                                                                                       
--- /dev/null                                                                                                                                                                                                                                                                                
+++ b/foo                                                                                                                                                                                                                                                                                    
@@ -0,0 +1 @@                                                                                                                                                                                                                                                                                
+foo        
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...