Как мне воспроизвести мои коммиты из локального репозитория Git, помимо проекта, который я разветвлял на github.com? - PullRequest
10 голосов
/ 22 сентября 2009

Да, я знаю, что должен был с самого начала разогнать проект, но сейчас я нахожусь в такой ситуации. :)

У меня есть локальный репозиторий Git, в котором содержится мой блог на локальном компьютере с историей коммитов в течение нескольких месяцев. Первоначально я просто скачал файлы из хранилища http://github.com/mojombo/mojombo.github.com, и я продолжил работу с моим локальным репозиторием Git, первый коммит был похож на последние файлы из репозитория mojombo.

Теперь я хотел бы раскошелиться на проект и сделать так, чтобы мои локальные коммиты репозитория Git воспроизводились поверх него, так что похоже, что я разветвлял проект с самого начала, а затем отодвинул его обратно в свою раздвоенную версию репозитория mojombo, на моем аккаунте GitHub:

http://github.com/program247365/mojombo.github.com

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

mobjombo repository:         1---2---3----23
                                  \
my blog repository commits:       24---25---

Какие команды Git я могу использовать именно для этого?

Я смотрел на этот вопрос . Придется ли мне добавлять репозиторий mojombo в качестве удаленного к моему проекту, а затем извлекать его, объединять, разрешать конфликты и затем выдвигать свой раздвоенный проект на GitHub?

Ответы [ 3 ]

15 голосов
/ 22 сентября 2009

Короче говоря:

Одним из решений является использование графтов для соединения истории, затем используйте git filter-branch, чтобы переписать историю в соответствии с этими трансплантатами, а затем при необходимости выполните слияние .

Обратите внимание, что решение для воспроизведения ваших изменений (ваших коммитов) поверх новой разработки в исходном репозитории (решение rebase ) является другим жизнеспособным решением.


Более длинная версия:

Предположим, что вы либо помните, либо можете найти, изучив источник и / или используя команды git, ревизию репозитория, из которого вы скачали снимок, и приступили к локальной разработке. Давайте назовем эту ревизию START или A.

Предположим, что ваша локальная отключенная история находится в клоне исходного репозитория. Это означает, что ваша локальная отключенная разработка находится в том же хранилище, что и полная история проекта. Предположим, что ваши локальные ветки находятся в ветке 'master' (и для простоты есть только одна ветвь).

Если вы не загрузили проект в хранилище с вашей локальной отключенной работой, вы можете сделать это с помощью:

$ git remote add origin git://github.com/mojombo/mojombo.github.com.git
$ git fetch origin

История теперь выглядит следующим образом:

*---*---*---*---*---A---*---*---*---*      <--- origin/master (remote-tracking branch)

                                     x---y---*---*---*      <--- master (your local disconnected history)

Коммит с именем A на приведенной выше диаграмме - это коммит START, который вы загрузили в виде моментального снимка и отключили локальную разработку.

Есть две возможности: вы сделали снимок «А» в качестве начального коммита «x», или первый коммит, который вы сделали, был с вашими локальными изменениями.

В первом случае (вы зафиксировали исходное начальное состояние, например, как «Первоначальная фиксация» или «Импорт»), вы бы хотели, чтобы подключенная история выглядела так:

*---*---*---*---*---A---*---*---*---*      <--- origin/master (remote-tracking branch)
                                      \
                                        \-y---*---*---*       <--- master (your local disconnected history)

т.е. Ваш первый оригинальный коммит 'y' будет иметь 'A' в качестве родителя.

Во втором случае (вы зафиксировали свои изменения) вы бы хотели, чтобы подключенная история выглядела так:

*---*---*---*---*---A---*---*---*---*           <--- origin/master (remote-tracking branch)
                                      \
                                        \-x---y---*---*---*      <--- master (your local disconnected history)

т.е. вы хотите, чтобы первый коммит 'x' имел 'A' в качестве родителя.

В обоих случаях вы хотите найти полный идентификатор SHA-1 коммита 'A' и полные идентификаторы SHA-1 коммитов 'x' и 'y'.

Вы можете найти SHA-1 коммита 'A' (при условии, что вы его еще не знаете) с помощью git rev-parse :

$ git rev-parse A     # or A^{commit}
437b1b20df4b356c9342dac8d38849f24ef44f27

(суффикс '^ {commit}' может понадобиться, чтобы убедиться, что вы нашли commit SHA-1, что важно, если вы, например, знаете «A» по его тегу, например, «v0» .99 '; в вашем случае это не нужно, поскольку в рассматриваемом хранилище теги не используются).

Вы можете найти SHA-1 коммитов 'x' и 'y', используя git rev-list (при условии, что ваша разработка была завершена на ветви 'master'):

$ git rev-list --topo-order master | tail -2
8bc9a0c769ac1df7820f2dbf8f7b7d64835e3c68
e83c5163316f89bfbde7d9ab23ca2e25604af290

("| tail -2" здесь, чтобы найти последние два коммита в сгенерированном списке; вам не нужно использовать его, если у вас его нет).

Примечание: во всех приведенных выше примерах полный SHA-1 является примерами и не должен использоваться как есть!

Давайте назовем коммит, для которого вы хотите иметь «A» (или «START») в качестве родителя, как FIRST (это будет «x» или «y», в зависимости от вашего случая, как указано выше). Теперь мы используйте механизм прививки , чтобы соединить историю:

$ echo "<SHA-1 of FIRST> <SHA-1 of START>" > .git/info/grafts

Затем вы должны проверить, правильно ли вы подключили (присоединились) историю, используя графический браузер истории, такой как gitk, или QGit, или GitX, если вы используете MacOS X, или даже "git log --graph", или "git show-branch ", например:

$ gitk master origin/master    # or --all

(где gitk здесь только в качестве примера; если вы используете «git show branch», вы не всегда можете использовать опцию «--all»).

Наконец, мы, вероятно, хотели бы сделать эти изменения постоянными, поэтому любой, кто извлечет их из нашего хранилища, также подключит историю. Мы можем сделать это с помощью git filter-branch :

$ git filter-branch master

У вас будет оригинальная (отключенная) история в 'refs / original / master'.

Теперь вы можете удалить файл трансплантатов:

$ rm .git/info/grafts

Теперь вы сможете объединить новые разработки для исходного репозитория:

$ git merge origin/master

Настройка конфигурации для каждой ветки, так что было бы достаточно просто выполнить «git pull», когда на ветке «master» извлекать (объединять) изменения в исходном (al) репозитории, оставленном в качестве упражнения для читателя. .: -)


Примечание: решение для перебазирования *1109* приведет к следующей истории (при условии, что у нас есть случай, когда первый комитт был простым импортом):

*---*---*---*---*---A---*---*---*---*                                      <--- origin/master (remote-tracking branch)
                                                                     \
                                                                       \-y'---*'---*'---*'      <--- master (your local disconnected history)

(где y' означает, что коммит y был изменен: он должен быть примерно таким же набором изменений, но он отличается от коммита).

5 голосов
/ 22 сентября 2009

Когда я пытался git pull, он выдавал следующую ошибку:

$ git pull grid master:master
! [rejected]        master     -> master  (non fast forward)

В моем конкретном случае мне показалось, что git rebase - это путь для меня, как показано на следующих шагах:

#Clone my forked project from github
git clone git@github.com:program247365/mojombo.github.com.git 

#Add my repo as a remote repo, with the alias 'grid'
git remote add grid "path/to/remote/gitrep/with/all/history/unrelated/to/mojombo/" 

#Rebase my commits on top of mojombo's
git rebase master grid/master

#Switch to the local master branch 
git checkout master

#Call up my mergetool via git, to start rectifying the conflicts that emerge between my repo, and mojombo's
git mergetool

#Push my rebased/combined repo back to Github.com
git push github
4 голосов
/ 22 сентября 2009

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

  1. Репо Fork Mojombo в GitHub.
  2. Клонируйте свою раздвоенную копию.
  3. Объедините ваши изменения с существующим (оригинальным) хранилищем.
  4. Удалите исходный репозиторий (если хотите, но он вам больше не нужен).

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

$ git clone git://github.com/$YOUR_USERNAME/$YOUR_PROJECT.git  # Clone your GitHub fork (#2 from above)
$ git pull /path/to/your/original/repo master:master           # Clone your original repo's master branch into your new repo (cloned from GitHub)
$ rm -rf /path/to/your/original/repo                           # Might as well delete the original -- you don't need it anymore, since all your history is in your new repo

Таким образом, этот метод объединит все изменения, которые вы сделали в старом репо (сохраняя при этом историю развития), и в то же время извлечет историю mojombo, и , что позволит вам идти в ногу с Изменения mojombo / легко вносить изменения обратно в репо, если применимо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...