2010-03-14 1 views
4

Это довольно странно, но я не могу выполнить довольно обычную операцию с git. В основном, я хочу, чтобы проверить ветвь функции, а не использовать ее голову, но используя SHA id. Этот SHA указывает между слияниями с главной ветвью.Git. Отверстие функции проверки между коммитами слияния

Проблема в том, что все, что я получаю, это просто ветвь мастера без фиксации от ветви функции. В настоящее время я пытаюсь исправить регрессию, введенную ранее в главной ветке.

Просто чтобы быть более описательным характером, я выстроил небольшой Баш скрипт, чтобы воссоздать хранилище проблемы:

#!/bin/bash 

rm -rf ./.git 
git init 

echo "test1" > test1.txt 
git add test1.txt 
git commit -m "test1" -a 

git checkout -b patches master 

echo "test2" > test2.txt 
git add test2.txt 
git commit -m "test2" -a 

git checkout master 

echo "test3" > test3.txt 
git add test3.txt 
git commit -m "test3" -a 

echo "test4" > test4.txt 
git add test4.txt 
git commit -m "test4" -a 

echo "test5" > test5.txt 
git add test5.txt 
git commit -m "test5" -a 

git checkout patches 
git merge master  

#Now how to get a branch having all commits from patches + test3.txt + test4.txt - test5.txt ??? 

В принципе все, что я хочу, это просто кассу филиала «заплаты» с файлами 1-4, но не включая test5.txt.

Выполнение: git checkout [sha_where_test4.txt_entered]

... просто дает ветвь с test1, test3, test4, но исключая test2.txt

Более сложный пример:

#!/bin/bash 

rm -rf ./.git 
git init 

echo "test1" > test1.txt 
git add test1.txt 
git commit -m "test1" -a 

git checkout -b patches master 

echo "test2" > test2.txt 
git add test2.txt 
git commit -m "test2" -a 

git checkout master 

echo "test3" > test3.txt 
git add test3.txt 
git commit -m "test3" -a 

echo "test4" > test4.txt 
git add test4.txt 
git commit -m "test4" -a 

echo "test5" > test5.txt 
git add test5.txt 
git commit -m "test5" -a 

git checkout patches 
git merge master 

echo "test6" > test6.txt 
git add test6.txt 
git commit -m "test6" -a 

#Now how to get a branch having all commits from patches + test3.txt + test4.txt - test5.txt ??? 
git log --topo-order | cat 

# Now I need something to help me going back to history 
# without manually calculating that patches~2 sha's 
git checkout -b patches.tmp master~1 
git merge patches~2 

Спасибо.

ответ

1

Что касается вашего первого примера, вам нужно переигрывать test3 и 4 на вершине test2: это классический case of rebase --onto:

Начать с:

alt text http://img169.imageshack.us/img169/2255/gitr1.png

Марки ток пластыри заложением, и переместить ветвь патчи, где вы хотели бы закончить (test4):

C:\Prog\Git\tests\rep\main>git checkout patches 
Switched to branch 'patches' 

C:\Prog\Git\tests\rep\main>git checkout -b tmp 
Switched to a new branch 'tmp' 

C:\Prog\Git\tests\rep\main>git checkout patches 
Switched to branch 'patches' 

C:\Prog\Git\tests\rep\main>git reset --hard master~1 
HEAD is now at 8448d0f test4 

Это дает вам:

alt text http://img169.imageshack.us/img169/4826/gitr2.png

И просто перебазироваться на то, что вы хотите, чтобы правильная последовательность фиксаций:

C:\Prog\Git\tests\rep\main>git checkout tmp 
Switched to branch 'tmp' 

C:\Prog\Git\tests\rep\main>git rebase --onto tmp tmp~1 patches 
First, rewinding head to replay your work on top of it... 
Applying: test3 
Applying: test4 

Что дает:

alt text http://img52.imageshack.us/img52/372/gitr3.png

Это работает только для линейного набора Обязуется перемещаться.

+0

Довольно аккуратный. Похоже на черную магию. Я просто пытаюсь понять, почему коммиты перемещались поверх патчей вместо tmp, как предлагалось --onto tmp. Согласно руководству git rebase [--onto ] [], новая база tmp! Я что-то пропустил? – MageSlayer

+0

@mageslayer: commits не двигался поверх 'patches', но поверх' tmp'. 'newbase' действительно' tmp'. 'patches' заканчивается на правом коммите просто потому, что перед' rebase -onto' я перезагружаю его в нужном месте назначения, в котором я хотел, чтобы он находился. – VonC

+0

@mageslayer: поскольку «ветка» в Git на самом деле является ярлыком на кончике графического пути, вы можете смело перемещать эту метку вокруг ... за исключением того, что вы уже опубликовали эту ветку ('push') что означало бы мир боли для любого, кто вытащил из вашей (новой) ветви: все будет снова слито. – VonC

0

A git merge Операция не возвращается и не изменяет историю, а создает новую фиксацию, указывающую на две истории, из которой он пришел. Так, в картинах, что у вас есть что-то вроде этого:

 
    2-----------\ 
/   \ 
1---3---4---5---M (HEAD) 

Когда вы перемотать историю, чтобы вернуться к пересмотру 4, вы получаете файлы 1, 3 и 4, но не 2.

+0

Да. Ты прав. Проблема в том, что мне нужно, чтобы test2.txt – MageSlayer

+0

@ answerh ответ описывает один из способов сделать это, создав * новый * слияние фиксации. –

+0

Я ценю его ответ, но это слишком много работы imho. Я уже копаю в направлении cherrypick. Однако не совсем успешно. – MageSlayer

1

Такого смысла нет. Здесь у вас есть два параллельных пути развития: один содержит файлы test1 и test2, другие - файлы test1, test3, test4 и test5. Однако вы можете создать такую ​​точку с слиянием.

Проверьте SHA1 для фиксации, которая добавляет test4, и объединится с фиксацией, которая добавляет test2. Например, после выполнения вашего скрипта мой репозиторий выглядит следующим образом:

* b054987 (HEAD, patches) Merge branch 'master' into patches 
|\ 
* | 5ae790f test2 
| * f2a3dac (master) test5 
| * 70e8cd2 test4 
| * c4102ed test3 
|/ 
* d448eaa test1 

На этом, запустите:

% git checkout 70e8c 
% git merge 5ae79 

В результате головка, которая содержит файлы 1-4:

* bcc8f7a (HEAD) Merge commit '5ae79' into HEAD 
|\ 
| | * b054987 (patches) Merge branch 'master' into patches 
| | |\ 
| |// 
| * | 5ae790f test2 
| | * f2a3dac (master) test5 
| |/ 
|/| 
* | 70e8cd2 test4 
* | c4102ed test3 
|/ 
* d448eaa test1 

% ls 
test1.txt test2.txt test3.txt test4.txt 

Теперь вы можете создать ветку с этой точки зрения.

+0

Конечно, я могу сделать это вручную, но для этого требуется большая работа. Боюсь, что это не поможет мне и здесь. – MageSlayer

+0

Но это делает то, что вы хотите, просто вызовите ветку 'patches' после слияния. Если нет, я не уверен, чего вы хотите достичь? Нет смысла в описываемой вами разработке, содержащей файлы с 1 по 4, поэтому вам нужно создать такую ​​точку. Я не думаю, что какой-либо другой VCS сможет проверить фиксацию, которая не существует ... –

+0

В основном я пытаюсь представить эту проверку как линейный набор исправлений, чтобы иметь возможность делить эту ветвь. Ваше решение отлично действует, за исключением того, что мне нужно вручную выяснить, коммиты refs сливаются в две ветки. – MageSlayer