Віддалено перейменовуючи гілки в Git


407

Якщо є сховище, до якого я маю git://доступ (і зазвичай просто натискаю + потягніть), чи є спосіб перейменувати гілки в цьому сховищі так само, як і з місцевим git branch -m?


48
Зв'язане "дублікат" питання просить перейменувати гілку "як локально, так і віддалено". Це питання лише задає питання про те, як віддалено перейменовувати гілки, що дозволяє спростити процес. Це те , що я роблю , щоб перейменувати гілку на сервері без необхідності перевірки та / або створити локальну гілка: git push origin origin/old_name:refs/heads/new_name && git push origin :old_name.
sschuberth

1
@sschuberth: ви можете дати обидві команди за один раз. І це справді має бути відповіддю на це питання.
Йоахім Брейтнер

2
@JoachimBreitner Ви маєте рацію, я зробив цю оптимізацію вже в цьому моєму сценарії .
sschuberth

1
@sschuberth, ви можете опублікувати свій коментар як відповідь, оскільки мені це подобається краще, ніж інші нижче.
phatmann

Відповіді:


480

Вам просто потрібно створити нову локальну гілку з потрібним іменем, натиснути її на пульт та видалити стару віддалену гілку:

$ git branch new-branch-name origin/old-branch-name
$ git push origin --set-upstream new-branch-name
$ git push origin :old-branch-name

Потім, щоб побачити стару назву гілки, кожен клієнт сховища повинен був би зробити:

$ git fetch origin
$ git remote prune origin

ПРИМІТКА. Якщо ваша стара гілка є вашою основною гілкою, ви повинні змінити свої основні настройки гілки. Інакше при запуску $ git push origin :old-branch-nameви отримаєте помилку "видалення поточної гілки заборонено" .


8
Ну, якщо старі та нові імена однакові, то це означає, що вам не потрібно перейменовувати гілку, тому немає сенсу виконувати команду в першу чергу ;-)
Sylvain Defresne

9
Звичайно. Я просто маю на увазі, що якщо ви називаєте це автоматизованим способом (як функціональну частину іншого сценарію), ви також можете не зробити це неправильно, якщо ви зможете цього уникнути.
Таємничий День

9
Шлях Дена: переупорядкуйте команди, щоб вони завжди просто працювали. Шлях Earth Engine: завжди пам’ятайте, щоб перевірити, чи ви втрачаєте дані. Я знаю, яку вибрати.
Дорадус

2
Користувачі можуть просто запускати: git fetch origin --prune(щоб ефективно отримати нові гілки, а також позбутися посилань, вже не на пульті).
DolphinDream

2
Можна використовувати -dабо --deleteзамість них :у новіших версіях git.
Zitrax

285

Якщо ви просто хочете віддалено перейменувати гілки, не перейменовуючи при цьому жодних локальних гілок , це можна зробити за допомогою однієї команди:

git push <remote> <remote>/<old_name>:refs/heads/<new_name> :<old_name>

Я написав цей скрипт ( git-rename-remote-branch ), який надає зручний ярлик, щоб зробити це вище легко.

Як функція bash:

git-rename-remote-branch(){
  if [ $# -ne 3 ]; then
    echo "Rationale : Rename a branch on the server without checking it out."
    echo "Usage     : $(basename $0) <remote> <old name> <new name>"
    echo "Example   : $(basename $0) origin master release"
    exit 1 
  fi

  git push $1 $1/$2:refs/heads/$3 :$2
}

Для інтеграції коментаря @ ksrb : Це, в основному, це два git push <remote> <remote>/<old_name>:refs/heads/<new_name>натискання в одній команді, спочатку натиснути нову віддалену гілку на основі старої гілки віддаленого відстеження, а потім git push <remote> :<old_name>видалити стару віддалену гілку.


10
Для тих, хто хотів би псевдонім цієї команди: rename = "! F () {git push origin origin / $ 1: refs / heads / $ 2: $ 1;}; f" це може використовуватися як> git rename <old_name> < new_name>
Джонатан Шмідт

33
Для тих, хто цікавиться, що насправді ця команда означає, що це по суті, 2 git push <remote>/<old_name>:refs/heads/<new_name>натискання означає натиснути новий пульт, який використовує старий пульт як src, тоді git push [space]:<old_name> означає видалити старий віддалений
ksrb

3
Для чого потрібно використовувати refs/heads/name? Ви не можете просто скористатися nameбезпосередньо, зробивши першу команду git push <remote> <remote>/<old_name>:<new_name>?
Дрю Ноакс

6
Ні, оскільки віддалений відділення <new_name>ще не існує. Якщо гілки не існує, Git вимагає використовувати повне ім’я, оскільки в іншому випадку це <new_name>також може посилатися на ім'я тегу.
sschuberth

3
Ми використовуємо такий підхід у нашій системі побудови. Єдине застереження, з яким ми стикаємось, - якщо воно refs/heads/<new_name> вже існує. Видалення все ще вдається, в результаті чого <remote>/<old_name>видаляється лише. Деякі перевірки перед рукою легко можуть цього уникнути.
Апейрон

172

Перший замовлення у відділення, яке потрібно перейменувати:

git branch -m old_branch new_branch
git push -u origin new_branch

Щоб видалити стару гілку з remote:

git push origin :old_branch

12
Коли ви натискаєте перейменовану гілку (new_branch) на віддалену (початкову), ви також повинні встановити її верхній потік для відстеження гілки з новою назвою (наприклад git push -u origin new_branch), інакше перейменована гілка (new_branch) продовжить відстежувати походження / old_branch. І як тільки ви видалите віддалений old_branch, new_branch все одно буде відслідковувати походження / old_branch, хоча зараз ця гілка вже відсутня.
DolphinDream

@DolphinDream Я відредагував відповідь, щоб включити ваші корисні зміни в потоці.
mVChr

10

Звичайно. Просто перейменуйте гілку локально, натисніть нову гілку та натисніть на видалення старої.

Єдине справжнє питання полягає в тому, що інші користувачі репозиторію не будуть перейменовані локальними гілками відстеження.


1
тому при спробі видалити майстер я спробував $ git клон ../src $ cd src $ git гілка notmaster $ git checkout notmaster $ git branch -d master $ git push ../src: master Але він скаржиться: призначення refspec не відповідає існуючому посилання на пульті дистанційного управління і не починається з refs /, і ми не можемо відгадати префікс на основі джерела ref. помилка: не вдалося натиснути деякі відповіді на '../alpha/' У пульті дійсно є гілка під назвою master
kdt

2

TL; DR

"Перейменування" віддаленої гілки - це насправді двоетапний процес (не обов'язково впорядкований):

  • видалення старої віддаленої гілки ( git push [space]:<old_name>як пояснив ksrb );
  • натисніть на нову віддалену гілку (різниця між парою команд відповідей нижче).

Видалення

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

$ git push origin :in
  • fatal: "origin" не схоже на сховище git

  • fatal: Не вдалося прочитати з віддаленого сховища.

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

Це, ймовірно, пов’язано з тим, що для учасників конкурсу не буде завантажений приватний ключ (який TortoiseGit автоматично завантажується в конкурс ). Більше того, я помітив, що команди TortoiseGit не мають originв них посилання (наприклад git.exe push --progress "my_project" interesting_local:interesting).

Я також використовую Bitbucket і, як і інші веб-менеджери в режимі онлайн-git подібного роду (GitHub, GitLab), мені вдалося видалити віддалену гілку безпосередньо через їх інтерфейс (сторінку відділень):

Видалити гілку Bitbucket

Однак у TortoiseGit ви також можете видалити віддалені гілки за допомогою перегляду посилань :

Переглянути меню посилань

Клацнувши правою кнопкою миші на віддаленій гілці (видалений список), з'явиться варіант Видалити віддалену гілку :

Видалення відділення TortoiseGit віддалене

Натискання

Після видалення старої віддаленої гілки я натиснув безпосередньо в нову віддалену гілку через TortoiseGit, просто ввівши нове ім'я у полі Remote: у вікні Push: ця гілка була автоматично створена та видима у Bitbucket .

Однак якщо ви все ще вважаєте за краще це робити вручну, точкою, яка ще не згадується в цій темі, є -u= --set-upstream.

У git pushдокументах - -uце лише псевдонім --set-upstream, тому команди у відповідях Sylvain ( -set-upstream new-branch) та Shashank ( -u origin new_branch) еквівалентні, оскільки віддалене посилання за замовчуванням до,origin якщо раніше не було визначено жодного іншого ref:

  • git push origin -u new_branch= git push -u new_branch з опису документів :

    Якщо конфігурація відсутня, вона за замовчуванням origin.

Зрештою, я вручну не вводив і не використовував жодної команди, запропонованої іншими відповідями, тут, можливо, це може бути корисним іншим у подібній ситуації.


проблема полягає в тому, що ваш пульт не викликається origin. Ви маєте назвати пульт, як ви отримаєте його від виконання команди git remote. Git працює з sshтим, що означає, що ви використовуєте відкриті + приватні ключі. Я припускаю, що Autoload Putty keysTortoiseGit просто завантажує необхідні ключі, щоб ви взагалі нічого не робили за допомогою віддаленої посилання. Останнє - git push -uце не псевдонім для просування у віддалену гілку, це псевдонім для просування у віддалену гілку , створену локально, і її віддалений посилання ще не має цієї гілки .
juanecabellob

1
@juancab -u- псевдонім --set-upstreamі "якщо конфігурація відсутня, вона за замовчуваннямorigin ". Sylvain і Shashank використовують це для просування в новостворену віддалену гілку . Ключовий питання може бути пов'язано з Pageant , не маючи його завантаженні , коли я намагався git push origin :inна раковині. Тож я не розумію вашої суті, я просто вказав мої та не адресовані деталі в інших відповідях, пояснив їх і вирішив.
CPHPython

Ви констатуєте неправильні речі, і значна частина цієї відповіді не пов'язана з самим питанням. Якщо ви вказуєте на те, що для вас спрацювало, я рекомендую обмежити відповідь на те, що це спрацювало, і якщо ви дійсно хочете дати пояснення, будь ласка, повідомте про це краще. Btw: -uпсевдонім для, --set-upstreamале це не псевдонім для просування в віддалену гілку, як ви вже говорили. Щоб просунутись у віддалену гілку, вам однозначно потрібно git push <remote>, і якщо її ще немає у віддаленій, ви додасте git push -u <remote>. Тому -uвикористовується для створення посилання на гілку у віддаленому режимі.
juanecabellob

1
@juancab, можливо, те, що ви вважали неправильним, було переважно псевдонімом фразування або вибором слів. Я реструктурував свою відповідь і перефразував її, щоб дати повне пояснення рішення (-ів), яке я знайшов перейменувати віддалену гілку.
CPHPython

Я б переформулював це далі. Зараз це має більше сенсу, але це все ще занадто довго. Я був би більш конкретним щодо проблеми, тобто заявляю, що запропоновані рішення для користувачів TortoiseGit не будуть працювати. Ви розповідаєте історію, і це бентежить і змушує користувачів уникати читання. Я відредагую вашу відповідь пропозицією.
juanecabellob

1

Я не знаю чому, але відповідь @Sylvain Defresne не працює для мене.

git branch new-branch-name origin/old-branch-name
git push origin --set-upstream new-branch-name
git push origin :old-branch-name

Мені потрібно зняти вихідний потік, і тоді я можу знову встановити потік. Далі, як я це зробив.

git checkout -b new-branch-name
git branch --unset-upstream
git push origin new-branch-name -u
git branch origin :old-branch-name

0

Я не знаю, це правильно чи неправильно, але я пересунув "стару назву" гілки на "нове ім'я" гілки, а потім видалив стару гілку повністю за допомогою наступних двох рядків:

git push origin old_branch:new_branch
git push origin :old_branch

Наскільки я можу сказати, саме так і роблять усі інші відповіді. Ваша відповідь просто більш лаконічна.
Чіткіший

-1

Ви можете створити нову гілку на основі гілки старої назви. Просто так, потім видаліть стару гілку, закінчившись !!!введіть тут опис зображення


Це GitHub, а не Git. ;)
Bouncner

-4

Додавши до вже наданих відповідей, ось версія, яка спочатку перевіряє, чи існує нова гілка (щоб ви могли сміливо її використовувати у сценарії)

if git ls-remote --heads "$remote" \
    | cut -f2 \
    | sed 's:refs/heads/::' \
    | grep -q ^"$newname"$; then
    echo "Error: $newname already exists"
    exit 1
fi
git push "$oldname" "$remote/$oldname:refs/heads/$newname" ":$oldname"

(чек з цієї відповіді )


Я б використав git show-ref --quiet --verify -- refs/heads/$new_nameзамість цього ls-remote | cut | sed | grep.
Енді
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.