2010-04-22 2 views
4

Я знаю this вопрос, но не уверен, как сопоставить его с моей текущей ситуацией. (Rebase страшно, погубило перебазироваться в два раза страшно!)Восстановление «старых коммитов» из нескольких перегибов git

Я начал с нескольких различных художественных ветвей моего хозяина:

master x-x-x-x-x-x-x-x-x-x 
      \  \ \ 
FeatureA  1-2-3 \ \ 
FeatureB    A-B \ 
FeatureC      X-Y-Z 

Я хотел объединить их все вместе и проверить они работали до слияния обратно на верх мастера, так что я сделал:

git checkout FeatureB 
git rebase FeatureA 
git mergetool //etc 
git rebase --continue 

Тогда

git checkout FeatureC 
git rebase FeatureB 
git mergetool //hack hack 
git rebase --continue 

Который оставляет меня с

master x-x-x-x-x-x-x-x-x-x 
      \ 
FeatureA  1-2-3 
        \ 
FeatureB   A'-B' 
         \ 
FeatureC     X'-Y'-Z' 

Тогда я исправил некоторые биты, которые не компилировать должным образом, и есть весь набор функций, до приемлемого состояния:

master x-x-x-x-x-x-x-x-x-x 
      \ 
FeatureA  1-2-3 
        \ 
FeatureB   A'-B' 
         \ 
FeatureC     X'-Y'-Z'-W 

Моя проблема заключается в том, что мои коллеги говорят мне что мы не готовы к FeatureA.

Есть ли способ сохранить всю мою работу, но также вернуться к ситуации, когда я могу просто переустановить FeatureC на Feature B?

+0

на самом деле я запутался, почему вы перебазировались на всех. Вероятно, вы, должно быть, создали новую ветку мастера или featureC (называемую функциямиABC, скажем) и объединили их в нее, оставив ветки функций неповрежденными. Хорошо сохранять независимую историю различных ветвей функций. – Cascabel

+1

@Jefromi, потому что я все еще учился ... – Benjol

+0

@Jefromi, я добавил то, что я понял из ваших комментариев, в качестве ответа, если вы хотите проверить (или даже потребовать его для себя) – Benjol

ответ

4

Это мое понимание того, что ответ, основываясь на комментариях:

Когда вы делаете перебазироваться, совершающие на вашем токе ветвь «отменена», а затем «повторно применена», но на самом деле они не отменены, они «запомнены» * и повторно применены с новыми идентификаторами, так, например, если я смотрю в git reflog show FeatureB, я получаю что-то вроде этого:

7832f89 [email protected]{0} rebase finished: refs/heads/FeatureB onto f4df3 
efd3fed [email protected]{1} commit: B 
f3f3d43 [email protected]{2} commit: A 
2f32fed [email protected]{3} branch: Created from HEAD 

Так как @Jefromi сказал, что оригиналы все еще существуют (SHA из A и B совершают в рефлоге не то же самое, что и в git log, что соответствуют А 'и В').

Аналогично, git reflog show FeatureC выглядит следующим образом

32873ef [email protected]{0} commit: W 
17dafb3 [email protected]{1} rebase finished: refs/heads/FeatureC onto 89289fe 
893eb78 [email protected]{2} commit: Z 
a78b873 [email protected]{3} commit: Y 
e78b873 [email protected]{4} commit: X 
378cbe3 [email protected]{5} branch: Created from HEAD 

Опять же, оригинальный Z, Y и X коммиты все еще там

Таким образом, решение моей проблемы заключается в создании нового филиала FeaturesBC выключить ГОЛОВКА мастера (например), то вишневого выбрать совершает FeatureB {2 & 1}, а затем FeatureC {4, 3, 2}, и (возможно) W:

git checkout master 
git checkout -b FeaturesBC 
git cherry-pick f3f3d43 
git cherry-pick efd3fed 
//etc... 

(Это, похоже, работал, мне пришлось заново делать некоторые из тех же слияний, но это было не так уж плохо)

Редактировать, из Jefromi:

Вишневый сбор, возможно, не было необходимости ,Вы также можете просто восстановить ветви, где ветви были до перебазирования:

git branch FeatureB-old efd3fed 
git branch FeatureC-old 893eb78 

Или, если вы хотите, чтобы выбросить нормированное положение FeatureB и FeatureC, возвращаясь туда, где они были раньше:

git branch -f FeatureB efd3fed 
git branch -f FeatureC 893eb78 

Наконец, обратите внимание: если вы хотите, вы можете использовать другие обозначения, указанные в логах - например, [email protected]{2} вместо 893eb78. Это означает «вторая предыдущая позиция FeatureC». Будьте осторожны, чтобы использовать это сразу после просмотра reflog, хотя, потому что, как только вы снова обновите ветвь (переместите ее, зафиксируйте на ней ...), вместо этого вместо 0ddbb3 будет ссылаться на 17dafb3.

Как @Jefromi прокомментировал мой вопрос:

Вы должны, вероятно, создали новую ветку от мастера или featureC (так называемого featuresABC, говорят), и объединен друг в него, оставляя ветви функций нетронутыми. Хорошо сохранять независимую историю различных ветвей функций.

* Для того, чтобы быть точным, старые фиксации объекты просто оставили в хранилище. В конечном итоге они будут обрезаны, так как вы не хотите, чтобы репо, полное старых оборванных коммитов; это произойдет в первый раз, когда запущен git gc, а фиксации не менее двух недель (настроено gc.pruneExpire).

0

Если все остальное не удается, вы можете перезапустить мастер и git cherry-pick все коммиты B или C для воссоздания этих ветвей. Я надеюсь, что кто-то уже написал сценарий, если это единственное решение ...

+0

Ну, честно говоря, я все время создавал резервную копию всего своего хранилища, поэтому я не полностью ввернута, но я бы хотел избежать повторного повторения всего предмета переустановки ... – Benjol

+0

Мое понимание (отсюда http: //stackoverflow.com/questions/2689634/do-i-need-to-perform-a-commit-after-a-rebase) заключается в том, что коммиты B и C были изменены с помощью rebase, так что это не сработает, или я что-то упускаю? – Benjol

+0

@Benjol: Вы частично правы: переустановленные коммиты - это действительно модифицированные версии оригиналов (в частности, у них разные родители и, возможно, несколько разных патчей), но оригиналы все еще существуют. Самый простой способ найти их - это, вероятно, 'git reflog show FeatureA' - это немного легче, чем собирать reflog' HEAD' и идентифицировать, какие строки принадлежат к каким ветвям. – Cascabel

0

Вы можете использовать git rebase --onto <old-merge-base from B> A C, чтобы переустановить все от C до A до точки на главном. он оставит вас:

master x-x-x-x-x-x-x-x-x-x 
      \  \ 
FeatureA  1-2-3 \ 
         \ 
FeatureB    A'-B' 
          \ 
FeatureC      X'-Y'-Z'-W 

, чтобы найти точку, где вы хотите, чтобы перебазировать на, вы можете использовать комбинацию reflog GIT и git merge-base - но вы также можете перебазироваться на слияния базу А, чтобы иметь историю похожее на следующее:

master x-x-x-x-x-x-x-x-x-x 
      |\ 
FeatureA | 1-2-3 
      \ 
FeatureB  A'-B' 
        \ 
FeatureC    X'-Y'-Z'-W 

(git rebase --onto $(git merge-base A master) A C)

+0

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

Смежные вопросы