Как переписать мои коммиты локального репозитория git, поверх проекта, который я разветкил на github.com?

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

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

Теперь я хотел бы разветкить проект, и мои локальные репозитории git будут переигрываться поверх него, так что похоже, что я начинал проект с самого начала, а затем нажимал его назад к моему раздвоенному verson mojombo repo, на моей учетной записи github:

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

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

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

Я хотел бы знать, какие команды git, я могу использовать именно это, чтобы сделать это?

Я рассмотрел этот вопрос. Должен ли я добавить mojombo repo в качестве удаленного в мой проект, а затем вытащить его, слить, разрешить конфликты, а затем нажать на мой разветвленный проект на github?

Ответ 1

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

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

В моем конкретном случае казалось, что git rebase был для меня способом, как показано здесь:

#Clone my forked project from github
git clone [email protected]: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

Ответ 2

Короче:

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

Обратите внимание, что решение для повторного изменения ваших изменений (ваших коммитов) поверх новой разработки в оригинальном репозитории (решение 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, которую вы загрузили в качестве моментального снимка, и отключили локальную разработку.

Есть две возможности: у вас есть моментальный снимок "A" в качестве первоначальной фиксации "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 ветвь фильтра:

$ git filter-branch master

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

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

$ rm .git/info/grafts

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

$ git merge origin/master

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


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

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

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

Ответ 3

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

  • Fork mojombo repo в GitHub.
  • Клонировать раздвоенную копию.
  • Объедините свои изменения с существующим (оригинальным) репозиторием.
  • Удалите исходный репозиторий (при желании, но вам это больше не нужно).

Итак, в принципе, после разблокировки 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 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/легко вносить изменения вернуться к своему репо, если это применимо.