Перемістіть локальний Git repo на новий віддалений, включаючи всі гілки та теги


551

У мене є місцеве репо Git, яке я хотів би перейти на нове віддалене репо (абсолютно нове репо, створене на Beanstalk, якщо це має значення).
У мого місцевого репо є кілька гілок та тегів, і я хотів би зберегти всю свою історію.

Схоже, я в основному просто потребую зробити git push, але це лише завантажує masterгілку.

Як я натискаю все, щоб отримати повну репліку місцевого репо на пульті?


Найкоротша і найпростіша відповідь - stackoverflow.com/a/39992258/6648326 .
MasterJoe2

Відповіді:


898

Щоб натиснути всі свої гілки , використовуйте будь-яку (замініть REMOTE на ім'я пульта, наприклад "походження"):

git push REMOTE '*:*'
git push REMOTE --all

Щоб натиснути всі свої теги :

git push REMOTE --tags

Нарешті, я думаю, ви можете зробити це все в одній команді за допомогою:

git push REMOTE --mirror

Однак, крім того --mirror, ви також підштовхнете ваші пульти, так що це може бути не саме те, що ви хочете.


53
--allзамість *:*здається більш доброзичливим
Idan K

56
Боже мій ............. Я розірвав весь Інтернет, і я дізнався, що перемикач "- всі" - це AAAAALLLLLLLLLLLLLLLL, який мені потрібен!
Ракіб

21
Просто зауваживши, що git push REMOTE --allповернувся, No refs in common and none specified;нічого не роблячи. Хоча git push REMOTE "*:*насправді відсунув усі гілки на віддалений.
Im0rtality

10
Використовуйте --dry run для перевірки того, що станеться, якщо у вас є локальні гілки "tmp" або "особливості", які ви не хочете оновлювати в REMOTE
Jonno,

55
Якщо оригінальний пульт все ще доступний, це непогано зробити git clone --mirror old-remote-url; cd repo.git; git push --mirror new-remote-url.
Сюзанна Дюперон

156

У випадку, як я, що ви отримали репо, а тепер перемикаєте віддалене джерело на інше репо, нове порожнє ...

Отже, у вас є репо і всі гілки всередині, але вам все одно потрібно перевірити ці гілки, щоб git push --allкоманда фактично їх також натискала.

Ви повинні зробити це, перш ніж натиснути:

for remote in `git branch -r | grep -v master `; do git checkout --track $remote ; done

Слідом за

git push --all

4
Це також дуже корисно, оскільки мені довелося перевірити всі гілки вручну. Це буде добре для наступного разу.
Cory Imdieke

10
Дивно, git push '*:*'відсунувши всі гілки. git push -allпросто штовхнув господаря. Я перевозив репо від github до бітбукета.
jerrymouse

3
Замість перевірки кожної окремої гілки вам слід просто зробити "git branch - track $ remote". У величезних репортах перевірка старої гілки займає колись
Моатас Ельмасрі

2
Мені довелося зробити невелику зміну, щоб це працювало: --track remotes/$remoteзамість --track $remote. Ось повний командний рядок:for remote in `git branch -r | grep -v master `; do git checkout --track remotes/$remote ; done
Адріан Т

Дякую, це працює для мене, вищезгадана відповідь також не працює.
Бенямін Джафарі

90

Ось ще одне те саме, що краще спрацювало для ситуації, в якій я був. Він вирішує проблему, коли у вас є більше одного віддаленого, хотіли б клонувати всі гілки у віддалений sourceдо віддалений, destinationале не заздалегідь перевіряючи їх.

(Проблема, яку я мав із рішенням Даніеля, полягала в тому, що він відмовився б від sourceвіддаленої перевірки гілки відстеження, якщо я раніше її вже перевірив, тобто він не оновлював би свою локальну гілку перед натиском)

git push destination +refs/remotes/source/*:refs/heads/*

Примітка. Якщо ви не використовуєте прямий CLI, ви повинні уникати зірочок:

git push destination +refs/remotes/source/\*:refs/heads/\*

це підштовхне всі гілки віддалено sourceдо головної гілки destination, можливо, здійснюючи нешвидкісний вперед рух. Вам все одно доведеться натискати теги окремо.


8
+1 Це працювало для мене, клонуючись від одного remoteдо іншого. Дякую!
Лоранс

4
Мені довелося уникнути зірочок:git push destination +refs/remotes/source/\*:refs/heads/\*
mattalxndr

2
Для мене це завершення натискання на гілку під назвою HEAD, що, на мою думку, не є намірним у цьому сценарії.
maxwellb

1
Ця відповідь була неймовірно корисною для мене. Єдина згадка про сторінку використання git-push (1) про використання зірочок - це крихітний приклад для цього --pruneваріанту.
laindir

4
Відмінна відповідь, набагато інша, ніж звичайний --mirrorпараметр, який всі рекомендують. Ідеально підходить для сценаріїв, коли ви просто хочете зберегти синхронізування двох дистанційних для автоматизації або аудиту.
Вініцій Ксав’є

15

Це найкоротший спосіб, який я знайшов, якщо пункт призначення порожній. Перейдіть у порожню папку, а потім:

# Note the period for cwd >>>>>>>>>>>>>>>>>>>>>>>> v
git clone --bare https://your-source-repo/repo.git .
git push --mirror https://your-destination-repo/repo.git

Замініть https://...і file:///your/repoт.д. за необхідності.


13

Сторінку сайту git-pushварто прочитати. У поєднанні з цим веб-сайтом я написав у своєму .git/config:

[remote "origin"]
    url = …
    fetch = …
    push = :
    push = refs/tags/*

В push = :означає «штовхати будь-які гілки" відповідність "(тобто гілки , які вже існують в віддаленому сховище і мають локальний аналог)», а push = refs/tags/*значить «штовхати все тег».

Тож тепер мені залишається лише бігти, git pushщоб натиснути всі відповідні гілки та всі теги.

Так, це не зовсім те, чого хотіла ОП (усі гілки для натискання вже повинні існувати на віддаленій стороні), але може бути корисним для тих, хто знайде це питання під час гуглінгу, "як я одночасно натискаю гілки та теги" час ».


13

У моєму випадку те, що працювало, було.

git push origin --all

4
Просто і легко. Це працює! originПсевдонім для віддаленого сховища URL Git.
Робити Nhu Vy

8

Дзеркальне відображення сховища

Створіть голий клон сховища.

git clone --bare https://github.com/exampleuser/old-repository.git

Дзеркальне натискання до нового сховища.

cd old-repository.git
git push --mirror https://github.com/exampleuser/new-repository.git

Видаліть тимчасове локальне сховище, яке ви створили на кроці 1.

cd ..
rm -rf old-repository.git

Дзеркальне відображення сховища, яке містить об'єкти Git Large File Storage

Створіть голий клон сховища. Замініть приклад ім'я користувача на ім’я особи чи організації, яка є власником сховища, і замініть ім'я прикладу сховища на ім’я сховища, яке ви хочете дублювати.

git clone --bare https://github.com/exampleuser/old-repository.git

Перейдіть до сховища, яке ви щойно клонували.

cd old-repository.git

Витягніть об'єкти Git Large File Storage у сховищі.

git lfs fetch --all

Дзеркальне натискання до нового сховища.

git push --mirror https://github.com/exampleuser/new-repository.git

Притисніть до дзеркала дзеркальні об'єкти Git Large File Storage.

git lfs push --all https://github.com/exampleuser/new-repository.git

Видаліть тимчасове локальне сховище, яке ви створили на кроці 1.

cd ..
rm -rf old-repository.git

Наведена вище інструкція надходить з довідки Github: https://help.github.com/articles/duplicating-a-repository/


1
Хоча це теоретично може відповісти на питання, бажано було б сюди включити істотні частини відповіді та надати посилання для довідки. Дивіться тут інструкції, як краще писати відповіді на основі посилань. Дякую!
GhostCat

5

Я знайшов вище відповіді, все ще є деякі незрозумілі речі, які вводять в оману користувачів. По-перше, це впевнено, що git push new_origin --allі git push new_origin --mirrorне можна дублювати всі гілки походження, він просто копіює наявні ваші локальні гілки до вашого нового_походження.

Нижче наведено два корисні методи, які я перевірив:

1, дублікат клоном голим репо. git clone --bare origin_url, потім увійдіть у папку, і git push new_origin_url --mirror. Таким чином, ви також можете скористатися git clone --mirror origin_urlобома --bareі --mirrorзавантажуватимете репо, не включаючи робочу область. будь ласка, зверніться до цього

2, Якщо у вас є git repo, використовуючи git clone, що означає, що у вас є гола робоча область repo та git, ви можете використовувати git remote add new_origin new_origin_url, і тоді git push new_origin +refs/remotes/origin/\*:refs/heads/\*, і потімgit push new_origin --tags

Таким чином ви отримаєте додаткову головну гілку, яка не має сенсу.


2

Щоб натиснути гілки та теги (але не віддалені):

git push origin 'refs/tags/*' 'refs/heads/*'

Це було б рівнозначно поєднанню --tagsта --allваріантів для git push, які, схоже, не дозволяють.


Чи є додаткова можливість натиснути з іншого пульта? Наприклад, з+refs/remotes/source/*
Ів Мартін

2

На основі відповіді @Daniel я зробив:

for remote in \`git branch | grep -v master\`
do 
    git push -u origin $remote
done

2
Ще краще, | grep -v masterйого можна замінити на | sed 's/\*//'(я припускаю, що ви виключили те, masterщоб уникнути неприємного маленького, *що є попереднім для обраної на даний момент гілки), що дозволяє вам включати masterта уникати будь-яких проблем, коли masterце не ваша обрана галузь. Також вибачте за некропостинг, просто ця відповідь мені сьогодні допомогла, і я хотів поділитися своєю модифікацією, якщо вона може допомогти іншим у моєму становищі ...
ToVine

1

Я виявив, що жодне з них, здається, не працює належним чином для мене. Сміливо запаліть це смертю, але чомусь не вдалося отримати інші варіанти належної роботи.

Очікуваний результат - репо "клонований" до іншого віддаленого (тобто від Github до іншого провайдера):

  • Усі гілки створюються на новому пульті
  • Вся історія філій створюється на новому пульті
    • (це було пропущено кожне рішення, яке я спробував)
  • Усі теги створюються на новому пульті
  • Джерело переміщується (заданий)
  • Не руйнує (надає паузу для параметра --mirror)

Основна проблема, яку я бачив, - це те, що всі віддалені відділення не були відтворені в новому віддаленому. Якщо команда зробила, новий пульт не мав історії гілок (тобто виконання git checkout branch; git logне показувало очікувані філійні зобов'язання).

Я помітив, git checkout -b branchnameце НЕ те саме, що git checkout branchname(останнє - те, що мені потрібно). Я зауважую, git checkout --track branchnameщо, здається, не тягнуло до історії філії.

Моє рішення (на основі повноважень):

Function Git-FetchRemoteBranches {
$originalbranch = (git symbolic-ref HEAD).split("/")[-1]

Foreach ($entry in (git branch -r)) {

If ($entry -like "*->*") {
  $branch = $entry.split("->")[2].split("/")[1]
}
  else {$branch = $entry.split("/")[1]}

Write-Host "--Trying git checkout " -NoNewline
Write-Host "$branch" -Foreground Yellow

git checkout $branch

Remove-Variable branch -Force

""}

#Switch back to original branch, if needed
If ( ((git symbolic-ref HEAD).split("/")[-1]) -ne $originalbranch) {
"Switching back to original branch"
git checkout $originalbranch
Remove-Variable originalbranch -Force
}
}

git clone http://remoterepo
cd remoterepo
Git-FetchRemoteBranches
git remote add newremote
git push newremote --all
git push newremote --tags #Not sure if neeeded, but added for good measure

1

Знизу команда натискає всі гілки ( включаючи ті, які ви ніколи не перевіряли, але присутні у вашому git repo, їх можна побачитиgit branch -a )

git push origin '*:*'

ПРИМІТКА. Ця команда стане корисною під час переміщення служби контролю версій ( тобто міграції з Gitlab на GitHub )


1
Міграція між службами контролю версій, і саме це я шукаю, ура!
Лука Шполярич

1

Мені було перехід від однієї служби контролю версій до іншої і мені потрібно було клонувати всі сховища, включаючи всі гілки, теги та історію.

Для досягнення вище я зробив наступне:

  • вручну оформити всі гілки до локального сховища (сценарій для оформлення всіх показаних нижче),
  • git push origin '*:*'

.sh скрипт, який використовується для перевірки всіх гілок до локального сховища:

for branch in `git branch -a | grep remotes | grep -v HEAD | grep -v master `; do
   git branch --track ${branch#remotes/origin/} $branch
done
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.