Страницы

Поиск по вопросам

Показаны сообщения с ярлыком git-remote. Показать все сообщения
Показаны сообщения с ярлыком git-remote. Показать все сообщения

понедельник, 13 апреля 2020 г.

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

#git #git_commit #git_remote #git_push

                    
Есть два репозитория:


голый (bare) репозиторий, из него все берут копию, в нем есть  мастер ветка, которая
всегда соответствует production состоянию
есть локальный репозиторий


Разработчик откатывается к предыдущем коммиту в локальном репозитории git reset --soft,
потом делает коммит, потом пуш.

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

Подскажите, пожалуйста, как правильно откатиться до коммита и залить это на удаленный
репозиторий?
    


Ответы

Ответ 1



Для простоты предположим, что проблемный коммит только один. Чтобы откатить опубликованный (push) коммит, есть два основных пути: git revert номер_проблемного_коммита. Создаёт второй, "противоположный" коммит, "со знаком минус". После его публикации получится состояние, как до проблемного коммита, но в истории останется пара ненужный-коммит + отмена-ненужного-коммита. git push --force. Перед этим нужен git reset, как советуют в комментариях. Эту опцию следует использовать с осторожностью. Рассмотрим следующие случаи: Никто ещё не увидел опубликовынные изменения (в том числе "роботы", которые могут что-то автоматически делать при push'е). Тогда --force наилучший вариант. Несколько человек уже обновились после неудачного коммита. Тогда перед использованием --force следует их уведомить, так как на их стороне --force может "взбаламутить" ситуацию и потребовать дополнительных действий. Если тут же вместо проблемного коммита не положить ещё какой-нибудь другой коммит, то проблемный коммит может снова попасть на сервер (даже без --force'а) от этих разработчиков. Кто-то уже опубликовал изменения поверх неудачного коммита. Тогда --force затрёт их новые коммиты. От этого можно защититься опцией --force-with-lease. В этом случае нужно обновиться и делать git rebase -i, а потом уже --force (причём во время этой операции могут набежать ещё новые коммиты). Тут git revert будет более уместен. Много человек уже обновилось, есть несколько опубликованных или неопубликованных изменений "поверх" плохого коммита: git revert.

Ответ 2



как вариант git reflog - выдаст список HEAD c номерами и описанием, достаточно выбрать интересуещее вас состояние и сделать сброс до этого HEAD. git reset --hard HEAD @{номер} HEAD – это указатель на текущую ветку, которая, в свою очередь, является указателем на последний коммит, сделанный в этой ветке. Это значит, что HEAD будет родителем следующего созданного коммита. Как правило, самое простое считать HEAD снимком вашего последнего коммита.

Ответ 3



В зависимости от платформы, Вы можете написать так: GitHub откат на 1 коммит локально: git reset --hard HEAD~1 Примечание: это потенциально опасная команда, так как она сбрасывает все ваши незафиксированные изменения. Потом удаляете в репозитории удаленно командой: git push origin -f По аналогии на BitBucket откат на 1 коммит локально: git reset --hard HEAD~1 и удаленно командой удаляете: git push -f origin HEAD^:master Примечание: вместо ветки master Вы можете использовать любую другую ветку. Этой командой Вы только удаляете с Bitbucket. HEAD~1 и HEAD^ могут быть взаимозаменяемыми.

четверг, 9 апреля 2020 г.

Как определить, является ли удалённый репозиторий «голым» или с рабочей копией?

#git #git_remote

                    
Нередко для того, чтобы локализовать проблему с использованием и настройкой удалённых
репозиториев в Git требуется узнать, является ли удалённый репозиторий «голым» ("bare")
или обычным, имеющим рабочую копию файлов.

Разумеется, если репозиторий на GitHub, Bitbucket, Gitlab или чём-то подобном, то
мы знаем точно. Также возможны решения вроде «залогиниться на сервер и посмотреть»
— но далеко не всегда это возможно. Ещё можно пробовать пушить какие-либо изменения
и смотреть на реакцию — но это меняет текущее состояние и тем самым усложняет проблему.

Мне нужен простой способ, который можно будет предлагать тем, от кого нужны уточнения
по вопросу (например, такому).


Обязательно не меняющий состояние удалённого и локального репозиториев
Желательно только средствами git и ОС (без установки дополнительного ПО)
Обходные решения не годятся («зайти и посмотреть», «спросить админа» и т.п.). Предположим,
что доступа по SSH нет или пользователь не умеет это делать.

    


Ответы

Ответ 1



Пока что лучшее, что я могу придумать — смотреть на имена удалённых репозиториев в их локальной фс и делать следующие предположения .git – с рабочей копией name.git – голый, bare. Дальше смотрим на вывод remote -v show и вырезаем из него путь — участок между именем репозитория (под которым он настроен локально) и именем папки. Нам этот путь не интересен, а раскрывать его может быть нежелательно. git remote -v show | sed s/'[[:space:]].*\/'/': '/g В моих экспериментах это возвращает следующее: С рабочей копией (склонировал из соседней папки) origin: .git (fetch) origin: .git (push) Голый (склонировал из Gitlab) origin: test-name.git (fetch) origin: test-name.git (push) Если репозиториев подключено несколько, то будет информация про каждый: origin: .git (fetch) origin: .git (push) backup: .git (fetch) backup: .git (push)

Ответ 2



git rev-parse --is-bare-repository When the repository is bare print "true", otherwise "false". https://stackoverflow.com/questions/1830701/how-do-i-check-if-a-repository-is-bare

воскресенье, 15 марта 2020 г.

Какие изменения происходят на удаленном сервере при git push?

#git #git_push #git_remote


Если я делаю push из локального репозитория в удаленный, то на удаленном файл полностью
изменяется на локальный? Или они сначала сравниваются и заливаются только изменения?
    


Ответы

Ответ 1



Git оперирует не файлами, а коммитами. Коммит — это «снимок» текущего состояния рабочей области. Он содержит полные версии файлов, а не изменения (также называемые дельтами или патчами). Подробнее о коммитах: Каким образом git сохраняет изменившуюся строку при коммите? Или они сначала сравниваются и заливаются только изменения? Отчасти вы правы: они действительно сначала сравниваются. Для сравнения файлов используется алгоритм Secure Hash Algorithm. Когда вы заливаете (push) очередные коммиты на удаленный сервер, Git сравнивает значение sha1 для каждого объекта. Если в его истории уже есть объект для этого значения, то повторно закачиваться он не будет. Если нет — то будет закачана полная версия этого файла, а точнее, содержащий его объект типа blob. на удаленном файл Как уже отметил alexander barakin, ваш удаленный сервер скорее всего типа bare, то есть не содержит файлов в рабочей области (а только внутренние файлы Git-репозитория).

Ответ 2



удалённый репозиторий — скорее всего — bare-репозиторий («голый»), т.е. возле него нет рабочего каталога (working directory), и, соответственно, никаких файлов, которые вы наблюдаете в своём рабочем каталоге. чтобы было понятней: в удалённом репозитории хранится практически то же, что и у вас в каталоге .git возле содержимого вашего рабочего каталога. а это, собственно, и есть git-репозиторий. исходя из вышеизложенного, надеюсь, становится понятно, что вопрос в текущей формулировке просто лишён смысла.

пятница, 13 марта 2020 г.

Клонирование git и push в два репозитория

#git #bitbucket #git_push #git_remote


Создал я локальный репозиторий у себя на компьютере:

cd /path/to/git/repo/
git init --bare --shared


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

cd /path/to/my/project/
git init
echo "Helo" >> hello.txt
git add .
git commit -m "Init"


Вот теперь я хочу в свой локальный репозиторий сделать пуш:

git remote add origin /path/to/git/repo/
git push origin master


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

cd /path/to/test/dir/
git clone /path/to/git/repo/


Теперь я хочу:


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


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

P.S. Отвечая на вопрос, зачем мне нужен локальный репозиторий. Мне нужно всегда иметь
на компьютере копию проекта с учетом всех gitignore. Даже тогда, когда у меня нет интернета.
Если есть возможность провернуть это без создания локального репозитория, можете дать
совет. Но вопрос, как запушить все коммиты на битбакет и не видеть постоянные сообщения
Everything up-to-date и другие, не смотря на то, что на компе у меня лежит целая куча
нужных мне коммитов, остается открытым
    


Ответы

Ответ 1



когда вы сделали git init, вы уже создали локальный репозиторий. он находится в под-каталоге .git. файлы же, которые вы создали в этом каталоге (/path/to/my/project/), а затем с помощью git add и git commit «добавили в репозиторий», на самом деле представляют собой лишь рабочую копию содержимого репозитория. репозиторий может быть и без рабочей копии. создаётся такой репозиторий при использовании опции --bare у команд git clone, git init. фактически вы получаете в таком репозитории то же содержимое, что и в каталоге .git у репозитория с рабочей копией. поэтому создавать ещё одну локальную копию репозитория, как сделали вы в каталоге /path/to/git/repo/, нет необходимости. всё содержимое репозитория, все коммиты, вся история — доступны в любой из копий git-репозитория и без доступа к интернету. и коммиты в эту копию репозитория вы можете делать без доступа к интернету. а как сделать вторую (третью, десятую) копию репозитория на каком-нибудь удалённом сервере, вы уже знаете: $ git remote add ... $ git push ... о том, как одной командой git push отправить изменения сразу в несколько репозиториев, написано, например, здесь и здесь. и по-русски: Отправить изменения в несколько репозиториев одной командой push

среда, 29 января 2020 г.

Как скачать только папки и файлы без репозитория?

#git #git_remote #git_clone


Мне надо просто слить репозиторий, без инициализции гита, без истории изменений,
без веток. Просто папки и файлы. Как это сделать? 

Проблема состоит в следующем: если делать git clone, то мы выкачиваем ее и всю историю
и по сути инициализируем гит. Если сделать git init, git add remote ..., git pull -
тоже инициализируем гит в директории. Других способов я не знаю.
    


Ответы

Ответ 1



Вариант А: мелкое (неглубокое, shallow) клонирование, а затем убрать все .git*. Это клонирует репо без истории: git clone --depth=1 git@github.com:xxx/yyy.git Вариант Б: git archive. Это сольёт файлы репо в ZIP'е: git archive --format zip --remote=git@github.com:xxx/yyy.git HEAD

Ответ 2



Есть несколько вариантов решения этой задачи: Через неполное клонирование Используйте параметр --depth команды git clone: git clone --depth=1 При этом создается «неполный» (shallow) репозиторий. Из документации: Create a shallow clone with a history truncated to the specified number of revisions. Создать неполный клон, в котором история будет ограничена указанным количеством последних коммитов. В Git до версии 2.0 неполный клон имел существенные ограничения на последующие pull/push/fetch, но начиная с 2.0 эти ограничения были устранены. Теперь вы можете «добрать» остальные коммиты или их часть следующим образом: # последние 10 коммитов git fetch --depth=10 # все git fetch --unshallow Через git archive Можно использовать команду git archive с параметром --remote. При этом удаленный сервер создает архив с содержимым последнего коммита и передает его вам. Локальный репозиторий при этом не создается. # сохранить в архив git archive --format=tar --remote= HEAD > archive.tar # сразу распаковать в текущий путь git archive --format=tar --remote= HEAD | tar -xf - Поддерживаемые форматы: tar, zip. Не каждый сервер Git поддерживает этот функционал, и многие накладывают ограничения на передаваемый адрес. Если вы неуспешно использовали относительный адрес (вроде master^^~2^~3), попробуйте точный sha-1 коммита.

четверг, 2 января 2020 г.

В каких ветках есть локальные изменения

#git #git_branch #git_remote


Как узнать, какие ветки содержат закоммиченные, но ещё не запушенные изменения?
    


Ответы

Ответ 1



примерно так: $ git branch -vv * master c488ea5 [origin/master: ahead 1, behind 1] 20160210184133 test ffc6775 [origin/test: ahead 1] 20160210183855 test2 ffc6775 [origin/test2: behind 1] 20160210183855 test3 7ff0eab 20160210184754 здесь мы видим, что ветки master, test и test2 «привязаны» к удалённым репозиториям (показано и имя репозитория и ветка «привязки»). также видно, что ветки master и test отстоят на один коммит каждая «впереди» (ahead 1), а master и test2 «позади» (behind 1) от содержимого удалённого репозитория. дополнительный вопрос, поднятый в комментариях: Как его сократить только до веток, у которых есть ahead/behind? И как убрать commit message из таблицы? с помощью опций команды branch, по-моему, никак. можно «порезать» вывод чем-то внешним. например, если доступна программа gnu/sed: $ git branch -vv | sed -rn 's/(: (ahead|behind) [0-9]+[^]]*\]).*/\1/p' * master c488ea5 [origin/master: ahead 1, behind 1] test ffc6775 [origin/test: ahead 1] test2 ffc6775 [origin/test2: behind 1]

Ответ 2



git remote show origin, где origin может быть надо заменить на ваш удалённый источник, настроенный в репозитории (в который, собственно, хотите запушить). В конце он выводит информацию о состоянии между ветками: Local refs configured for 'git push': develop pushes to develop (up to date) master pushes to master (local out of date) dummy pushes to dummy (fast-forwardable) up to date — ветки одинаковы, на удалённом сервере всё из неё есть local out of date — изменения с сервера затянуты, но в локальной ветке их ещё нет fast-forwardable — можно пушить, удалённая ветка сделает fast-forward до вашей

среда, 25 декабря 2019 г.

В чем разница между track, set-upstream-to и set-upstream?

#git #git_branch #git_remote


Не могу разобраться в теме "отслеживания веток"

Есть 3 команды которые вроде как выставляют для ветки отслеживание на удаленную ветку:

git branch --track 
git branch --set-upstream-to 
git branch --set-upstream


По мне, так они делают одно и тоже. Я не понимаю, зачем тогда их аж 3 штуки?
    


Ответы

Ответ 1



флаг --track можно использовать только при создании новых бранчей Флаги --set-upstream и --set-upstream-to меняют upstream для уже существующего бранча (если не указан --force). Можно считать --track шорткатом для --set-upstream --force Новый --set-upstream-to отличается от старого --set-upstream порядком аргументов, что позволяет менять upstream для текущего бранча без явного указания его имени: git branch --set-upstream-to=origin/master

вторник, 24 декабря 2019 г.

Cкачать (fetch) с GitLab содержимое запроса на слияние (merge request)

#git #gitlab #git_remote


Сервер Gitlab, организую работу через запросы на слияние (merge request, pull request).

При создании запроса хотелось бы иметь URL, из которого Jenkins смог бы выкачивать
последний коммит ветки, которая предлагается к слиянию.

Есть ли возможность в Gitlab получить такой URL?


какой-нибудь alias к ветке, предлагаемой к слиянию?
автоматически создаваемый предварительный коммит? (т.е. что бы получилось, если прямо
сейчас нажать кнопку Merge Request?


Знаю, что-то подобное возможно в Gitlab CI и GitHub CI, на этих коммитах даже тесты
прогоняются. Поэтому возможен и третий вариант:


Работать с Jenkins как с Gitlab CI?


Перейти полностью на Gitlab CI - не вариант, это будут неоправданные затраты.
    


Ответы

Ответ 1



автоматически создаваемый предварительный коммит? (т.е. что бы получилось, если прямо сейчас нажать кнопку Merge Request? Фича пока не реализована, можно проголосовать. какой-нибудь alias к ветке, предлагаемой к слиянию? Реализовано. На каждый merge request гитлаб создаёт внутри себя отдельный указатель в refs/merge-requests. Нужно просто настроить свой репозиторий, чтобы при git fetch забирать эти указатели. Открываем .git/config, находим в нём блок, соответствующий репозиторию. [remote "origin"] url = https://gitlab.com/gitlab-org/gitlab-ce.git fetch = +refs/heads/*:refs/remotes/origin/* Добавляем в него строку +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/*. Теперь должно выглядеть так: [remote "origin"] url = https://gitlab.com/gitlab-org/gitlab-ce.git fetch = +refs/heads/*:refs/remotes/origin/* fetch = +refs/merge-requests/*/head:refs/remotes/origin/merge-requests/* Обновляем данные: $ git fetch origin From https://gitlab.com/gitlab-org/gitlab-ce.git * [new ref] refs/merge-requests/1/head -> origin/merge-requests/1 * [new ref] refs/merge-requests/2/head -> origin/merge-requests/2 Теперь можно создать новую локальную ветку, отслеживающую соответствующий merge request. $ git checkout merge-requests/1 Branch merge-requests/1 set up to track remote branch merge-requests/1 from origin. Switched to a new branch 'merge-requests/1' Примеры взяты из документации GitLab. Там же есть более подробные инструкции.

пятница, 13 декабря 2019 г.

Отправить изменения в несколько репозиториев одной командой push

#git #git_push #git_remote


В своём локальном репозитории можно подключить несколько удалённых репозиториев (git
remote add ...) и отправлять в них изменения командой git push имя-репозитория имя-ветки
— по одной команде на каждый репозиторий.

А как это сделать одной командой git что-то-там? без написания скрипта или функции
или псевдонима (alias-а).
    


Ответы

Ответ 1



для каждого удалённого репозитория можно задать pushurl, т.е., url, по которому будут отправляться изменения по команде push. этот pushurl, кстати, может и не совпадать с url данного репозитория. вот такой фокус: делаете push, вроде бы, в репозиторий на bitbucket-е, а изменения идут на github. более того: таких pushurl-ов может быть больше одного. и изменения одной командой отправятся сразу по нескольким url-ам. добавляется pushurl с помощью команды примерно такого содержания: $ git remote set-url --add --push имя-репозитория url-репозитория от теории к практике. создадим три (чтоб наверняка) bare-репозитория: $ for i in 1 2 3; do git init --bare repo$i; done Initialized empty Git repository in ./repo1/ Initialized empty Git repository in ./repo2/ Initialized empty Git repository in ./repo3/ и сделаем клон первого из них: $ git clone repo1 work Cloning into 'work'... warning: You appear to have cloned an empty repository. done. $ cd work посмотрим умолчальную конфигурацию remote-ов: $ git config --get-regexp "^remote" remote.origin.url ../repo1 remote.origin.fetch +refs/heads/*:refs/remotes/origin/* а теперь добавим pushurl-ы для всех созданных bare-репозиториев, не забыв и про сам исходный репозиторий (../repo1): $ for i in 1 2 3; do git remote set-url --add --push origin ../repo$i; done $ git config --get-regexp "^remote" remote.origin.url ../repo1 remote.origin.fetch +refs/heads/*:refs/remotes/origin/* remote.origin.pushurl ../repo1 remote.origin.pushurl ../repo2 remote.origin.pushurl ../repo3 как видно, pushurl-ы благополучно добавились. создаём коммит и отправляем его командой push: $ date > file $ git add file $ git commit -m 1 [master (root-commit) 2d68407] 1 1 file changed, 1 insertion(+) create mode 100644 file $ git push Counting objects: 3, done. Writing objects: 100% (3/3), 228 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To ../repo1 * [new branch] master -> master Counting objects: 3, done. Writing objects: 100% (3/3), 228 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To ../repo2 * [new branch] master -> master Counting objects: 3, done. Writing objects: 100% (3/3), 228 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To ../repo3 * [new branch] master -> master вуаля! коммит отправился во все три bare-репозитория одной командой! а как насчёт других веток? создадим ещё одну ветку (new), добавим в неё коммит и отправим изменения: $ git checkout -b new Switched to a new branch 'new' $ date >> file $ git commit -am 2 [new c82bfe5] 2 1 file changed, 1 insertion(+) $ git push -u origin new Counting objects: 3, done. Writing objects: 100% (3/3), 264 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To ../repo1 * [new branch] new -> new Branch new set up to track remote branch new from origin. Counting objects: 3, done. Writing objects: 100% (3/3), 264 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To ../repo2 * [new branch] new -> new Branch new set up to track remote branch new from origin. Counting objects: 3, done. Writing objects: 100% (3/3), 264 bytes | 0 bytes/s, done. Total 3 (delta 0), reused 0 (delta 0) To ../repo3 * [new branch] new -> new Branch new set up to track remote branch new from origin. эта «магия» работает и с новыми ветками! коммит отправился в ветки new во всех трёх bare-репозиториях. ответ основан на информации из этого и этого ответов.

Ответ 2



Если вкратце. // Добавляем git remote add "all" git@github.com:fudeglan/gigalab.uz.git git remote set-url --add --push "all" git@github.com:fudeglan/gigalab.uz.git git remote set-url --add --push "all" git@bitbucket.org:fudeglan/gigalab.uz.git git remote set-url --add --push "all" git@gitlab.com:fudeglan/gigalab.uz.git // Отправляем git push all .git/config примерно будет таким [remote "all"] url = git@github.com:fudeglan/gigalab.uz.git fetch = +refs/heads/*:refs/remotes/all/* pushurl = git@github.com:fudeglan/gigalab.uz.git pushurl = git@bitbucket.org:fudeglan/gigalab.uz.git pushurl = git@gitlab.com:fudeglan/gigalab.uz.git

Как обнулить историю Git?

#git #git_commit #git_remote #git_push


Ситуация такая: на сервере удалил репозиторий и создал заново, с локального теперь
нужно сделать push, но если сделаю, то всю историю коммитов запишет на сервер.

Как начать с нуля?
    


Ответы

Ответ 1



Все эти инструкции верны, если на удаленном сервере у вас пусто, а локально - есть проект и репозиторий Git с историей, которую вы хотите удалить. Что будет потеряно безвозвратно Собственно, история. Вы точно хотите ее потерять? Ради нее весь Git и придумывался. Весь код в не-слитых (unmerged) ветках. Весь код в orphaned ветках. Метки (tags) Быстрый способ Найдите первый коммит в ветке, запомните его sha1. git log --oneline Переключитесь на тот коммит, который хотите сохранить в итоге. git checkout master Теперь используем git reset --soft чтобы сделать из всей истории один коммит (подробнее - пункт 4.1: Как вернуться (откатиться) к более раннему коммиту? ). git reset --soft git commit -m'слил историю в один коммит' Долгий способ Сделайте бэкап локального репозитория. Можно запушить на резервный удаленный репозиторий, а можно просто взять и переместить папку .git в другое место. mkdir ../git-backup mv .git ../git-backup/.git Если не переместили локально, а забэкапили куда-то еще: удаляем папку. rm -Rf .git Теперь заново инициализируем репозиторий: git init Добавляем все файлы в рабочей области и делаем коммит. git add . git commit -m'начал с нуля' Когда все готово Подключаем удаленный репозиторий и заливаем на него изменения: git remote add origin git push -u origin --all

Ответ 2



Сделать clone, скопировать файлы (без .git), сделать push! Нет? ))

Ответ 3



Эта команда делает совсем другое: стирает всю историю до commitId и возвращает рабочую область к его состоянию. При этом вы потеряете данные более поздних коммитов. git reset --hard commitId #УДАЛЯЕТ ИСТОРИЮ GIT

воскресенье, 1 декабря 2019 г.

Как настроить подключение к удаленному Git репозиторию

#git #ssh #git_remote


Как настроить подключение к удаленному Git-репозиторию, через SSH, на компьютере
с Windows 7 . И соответственно выкачать содержимое к себе на локальный сервер. 

Удаленный репозиторий находится на сервере с git. мне нужно просто склонировать содержимое.
никаких пушей обратно. там есть идентификация. сгенерил паблик кей и отослал спец-ту
на той стороне. как мне добавить ранее сгенеренный-свой ключ через консоль и подключиться
к серверу? какие команды..? Windows 7 на моей машине. 
    


Ответы

Ответ 1



Установка Если ещё не установлен, то Git можно взять здесь. Вместе с ним будет unix-like консоль Git Bash. https://github.com/git-for-windows/git/releases/ Клонирование через SSH Пример команды для клонирования через SSH. git clone git@github.com:brockgr/csshx.git В общем случае команда для клонирования по SSH выглядит так: git clone git@server.domain:user/reponame.git Не перепутайте с HTTPS, который потребует авторизации через логин-пароль: git clone https://github.com/brockgr/csshx.git Создание ssh-ключа. На Windows можно как через cmd, так и Git Bash, на *nix — просто в консоли. Но в cmd я не разбираюсь, поэтому привожу инструкцию только для Git Bash & *nix: ssh-keygen -t rsa -C "user.name@mail.domain" Можно выбрать passphrase, который повышает надёжность, но его нужно будет вводить каждый раз при использовании. Если забудете — ключ бесполезен для дальнейшего использования. После выполнения команды публичный ключ появляется соответственно в C:\Users\%username%\.ssh\id_rsa.pub ~/.ssh/id_rsa.pub Именно публичный ключ нужно передавать специалисту на той стороне. (Наверняка вы так и сделали, но всё-таки стоит об этом сказать) Если всё сделали правильно, то при попытке соединения по ssh ключ будет использоваться автоматически. Если ключ уже есть То его надо положить в c:\Users\%username%\.ssh. Если имя ключа отличается от id_rsa, то надо создать файл c:\Users\%username%\.ssh\config со следующим содержимым: Host: server.domain IdentityFile путь_и_имя_ключа

Ответ 2



На практике мне когда-то помогла эта статья - лучший пример из всего что я видел: http://habrahabr.ru/sandbox/37865/ В ней полностью показаны клиентские программы для работы с push-ом и pull-ом. У меня лично Windows недолюбливал родной Git клиент, но всегда прекрасно работает с Tortoise (есть в статье). В ней есть полное руководство по подключению. Не уверен правильная ли это аналогия, но вы можете поставить себе программу Composer и ей подобные, после чего можно через консоль Windows полностью клонировать себе репозиторий с Git-а. Если же касается более специфичного подключения именно к Git, то эта страница будет полезной: http://webhamster.ru/site/page/index/articles/comp/171 Добавил, как попросили, кратко содержимое статьи: Идем на официальную страницу Git http://git-scm.com, кликаем на Download for Windows. В открывшемся окне кликаем на Full installer for official Git. Запускаем полученный exe-шник. Я рекомендую выбрать "Run Git from the Windows Command Prompt". Все остальные опции можно оставлять по-умолчанию. После установки Git нужно перегрузиться или завершить сеанс пользователя и снова войти, чтобы применились изменения в системной переменной PATH. Далее нужно проверить, доступен ли Git для работы. В любом каталоге даем команду: git --version Если получаем информацию о версии, то Git установлен и работает. Если получаем информацию что программа git не найдена, разбираемся что сделали не так. Настройка SSH-ключей в Windows В операционной системе Windows генератор SSH-ключей включен в комплект поставки Git. Для генерации ключей необходимо запустить на выполнение файл C:\Program Files\Git\Git bash.vbs. Его можно запустить как обычный exe-шник. Откроется программа "Консоль git". В ней надо дать команду: ssh-keygen -t rsa -C "myemail@mail.ru" Будьте внимательны, в этой консоли подглючивает копи-паст, проще ввести команду вручную. В качестве email указываем свой почтовый ящик. На запрос "Enter file in which to save the key" просто нажимаем Enter. При запросе пароля "Enter passphrase" и "Enter same passphrase again" просто нажимаем Enter. В процессе генерации ключей в консоли будет выдаваться примерно следующая информация: Generating public/private rsa key pair. Enter file in which to save the key (/c/Documents and Settings/username/.ssh/id_rsa): Enter passphrase (empty for no passphrase): Enter same passphrase again: Your identification has been saved in /c/Documents and Settings/username/.ssh/id_rsa. Your public key has been saved in /c/Documents and Settings/username/.ssh/id_rsa.pub. The key fingerprint is: 51:db:73:e9:31:9f:51:a6:7a:c5:3d:da:9c:35:8f:95 myemail@mail.ru После выполнения этой программы, в каталоге C:\Documents and Settings\username.ssh будут лежать файлы id_rsa и id_rsa.pub, они нам пригодятся в дальнейшем. Установка SSH-ключа в GitHub Нас колько я помню, эта часть ответа несколько изменилась в современном дизайне GitHub-а, но интуитивно можо найти. Сразу после регистрации необходимо прописать в системе GutHub свой публичный ключ шифрования (открытый SSH-ключ). Для добавления ключа, надо в правом верхнем углу нажать "Account Settings". В открывшемся окне нужно кликнуть на пункт меню "SSH Public Keys", и нажать "Add Another Public Key". Появится два поля - название ключа (Title) и содержимое ключа (Key). В поле Title можно написать название компьютера, на котором сгенерирован публичный ключ. Можно писать по-русски. В поле Key надо вставить содержимое файла id_rsa.pub. Помните, в каком каталоге они находятся? Переходим в этот каталог, открываем любым текстовым редактором файл id_rsa.pub (именно с расширением .pub, не перепутайте). Выделяем весь текст, копируем, и вставляем на странице GitHub в поле Key. После добавления ключа, компьютер может соединяться с GitHub через программу git, и никаких ошибок не должно возникать. Работа с репозитарием на GitHub через программу Git Начиная с этого момента, пляски вокруг web-интерфейса GitHub можно считать законченными. Далее можно работать только используя программу git. Вначале нужно сделать небольшую настройку программы git: указать локальной системе git имя пользователя и email. Это делается следующими командами, которые можно выполнить, находясь в любом каталоге: git config --global user.name "YourFullName" git config --global user.email myemail@mail.ru где вместо YourFullName нужно написать свое имя, а вместо myemail@mail.ru - свой email. Эти значения используются для логина на GitHub. Поэтому на месте YourFullName нужно указать ваш логин на GitHub-е, а на месте myemail@mail.ru нужно указать email, который вы вводили при генерации ключей шифрования. После этих настроек, можно заливать свои файлы в репозитарий. Переходим в каталог со своим проектом, и даем команды: git init git add . git commit -a -m 'first commit' git remote add origin git@github.com:username/reponame.git git push -u origin master После этих команд на сервере GitHub образуется копии файлов того каталога, в котором были выполнены данные команды. Далее можно уже делать коммиты, заливки на сервер GitHub изменений, считывания изменений с сервера. Но это уже совсем другая история.

Ответ 3



Вам выше уже предоставили ссылки на скачивание. Повторяться не буду. После установки потребуется выбрать каталог в системе (или создать там, где захотите), где будет лежать локальная копия того, что есть в удаленном репозитории. После этого в этой директории: git init Не забудьте настроить свой гит через: git config --global user.name git config --global user.email Это особенно актуально для продукта атлассина crucible (для код ревью). Примечание: опцию --global использовать, если вы единственный пользователь гита на данном компьютере. Если нет, настройте гит под конкретного пользователя в системе Замечание про настройку пользователя скорее опционально. Изучите официальную пользовательскую документацию на сайте либо, после установки клиента под windows запустите git --help для получения справки. Для клонирования репозитория в свою локальную папку используется: git clone ssh://username@servername.com/git/folder/here Вы также можете воспользоваться графической версией ГИТа, хотя лично я предпочитаю везде пользовать консоль, мне она кажется более информативной.

пятница, 29 ноября 2019 г.

Откатить уже опубликованный коммит и опубликовать новый, не вызывая мержа у других

#git #git_commit #git_remote


Предположим, я сделал коммит X и опубликовал его на удаленный репозиторий (git push).
Все, у кого есть доступ к репозиторию обновились. 

Далее я обычно откатываю коммит через  git reset --hard HEAD~1, делаю изменения и
пушу через git push -f origin master, что полностью удаляет прошлый коммит. Однако,
если все снова запулят, то у них будет мерж удаленного коммита с новым.

Как этого избежать?
    


Ответы

Ответ 1



Если коммит попал в общую/стабильную ветку (т.е. ту, которой пользуется хоть кто-то ещё, обычно это master, develop и прочие), то его нельзя удалять. Можно только создать «отменяющий» коммит с помощью git revert (подробнее тут, пункт 5). Возможно, в вашем коммите оказались какие-то критические данные, например пароли или ключи. В этом случае бесполезно пытаться спасти их с помощью удаления коммита, который их содержит. Данные уже скомпрометированы, все пароли и ключи придётся менять. # отменяем последний коммит, доступный по указателю HEAD git revert HEAD # фиксируем отмену в новом коммите git commit -m'reverted the last commit' Если вы абсолютно уверены, что вы запушили «лишний» коммит в собственную ветку, что её никто не замержил в стабильную ветку и просто так не начал разработку от последнего вашего коммита, можно откатить локальную ветку к предыдущему коммиту, а потом переписать изменения в удалённой (подробнее тут, пункт 4.2) Внимание! Никогда не делайте так с общими ветками (master, develop и прочие). Если это категорически необходимо, обязательно и сразу же предупредите всех, кто работает с этим репозиторием. После переписывания последнего коммита в стабильной ветке им придётся вручную обновлять эту ветку на своей машине. Если у них есть какие-то новые коммиты, предком которых является удаляемый коммит, им придётся делать rebase на коммит. git reset HEAD^ git push -f Вот вам моя любимая схема, иллюстрирующая разные варианты решения.

Ответ 2



У них скорее всего будет не просто слияние с удалённым коммитом, но будут какие-то проблемы. Ведь у них в репозиториях лежат коммиты с родителем A, а в удалённом репозитории лежит другой коммит, но тоже с родителем A. Я, откровенно говоря, не знаю как поведёт себя git, но единтсвенным правильным решением в данной ситуации является откат всех локальных репозиториев точно так же, как Вы откатитились: git reset --hard HEAD~1, только потом git pull Вообще говоря за git push -f origin master, в репозиторий, который используется более чем одним человеком, бьют по лицу. Так делать можно только в ЭКСТРЕННЫХ случаях и только если вся команда в курсе происходящего и принимает соответсвующие меры на своих локальных копиях.

среда, 27 ноября 2019 г.

Обновление репозитория git без ввода паролей

#linux #git #git_remote #git_pull


Есть корпоративный аккаунт "А" с приватными репозиториями на github.com;
есть аккаунт "B" - мой обычный аккаунт, который имеет административный доступ к репозиториям
аккаунта "А". 

При обновлении репозитория на сервере через консоль командой git pull система каждый
раз запрашивает пароль. Ввожу пароль аккаунта "В" и команда успешно выполняетя.

Вопрос: как сделать так, чтобы при вводе команды из консоли, система не запрашивала
пароль? Это должно позволить выполнять обновление репозитория из php. 

Что для этого нужно, размещать какой-то специальный ключ на сервере? 
    


Ответы

Ответ 1



Запустите в консоли команду git remote -v и посмотрите, через какой протокол у вас осуществляется доступ к репозиторию. Если это https, то будет примерно следующий путь: https://github.com/USERNAME/OTHERREPOSITORY.git Для ssh будет такой: git@github.com:USERNAME/OTHERREPOSITORY.git https Требуется Git версии не ниже 1.7.10 В этом случае вам всегда требуется указывать пароль при общении с сервером. Git можно попросить сохранять на некоторое время (по умолчанию на 15 минут) введённые данные командой: > git config --global credential.helper cache При желании можно изменить стандартное время запоминания командой > git config --global credential.helper "cache --timeout=3600" (время указывается в секундах) Вы можете также указать git хранить ваши данные постоянно: > git config credential.helper store При этом ваши данные будут храниться в открытом виде в файле .git-credentials. Обнулить настройки этой возможности можно командой: > git config --unset credential.helper При желании можно подобное поведение для всех репозиториев, для этого нужно передать дополнительный ключ --global. В зависимости от этой настройки, информация с вашими данными будет расположена либо в каталоге проекта, либо в $HOME Для версий Git, ниже 1.7.10 Вы можете указать информацию для авторизации в url, по которому осуществляете доступ к репозиторию, для этого его нужно преобразовать так: https://username:password@github.com/USERNAME/OTHERREPOSITORY.git Измените текущий url в remote на указанный (как это сделать, описано ниже в ответе) и авторизация не будет запрашиваться. Помните, что и в этом случае ваши данные будут храниться в открытом виде. Для Git версии не ниже 0.99 Существует возможность настроить netrc SSH Про работу с запароленным ключём SSH знаю лишь то, что можно настроить ssh-agent, который аналогично позволит не вводить каждый раз пароль от ключа ssh. Для начала создайте ssh-ключ с помощью команды: > ssh-keygen Она попросит ввести имя файла (во многих случаях можно оставить имя по умолчанию) и пароль. Пароль при желании можно оставить пустым, для этого просто дважды нажмите Enter при запросе пароля (обычно рекомендуется устанавливать пароль). По умолчанию пара ключей появляется в каталоге ~/.ssh/. Вам нужно скопировать содержимое файла id_rsa.pub (если вы не задавали другое при создании ключа) и сохранить его в своём профиле на GitHub (Settings -> SSH Keys -> Add SSH key). После этого можно перейти к настройке ssh-agent: Выполните команду: > echo $SSH_AGENT_PID Если ssh-agent запущен, то должен вернуться его номер процесса. В этом случае можно пропустить следующий пункт и перейти к команде ssh-add. Если вернулась пустая строка, необходимо запустить ssh-agent перед продолжением. Запускаем ssh-agent в фоне: > eval "$(ssh-agent -s)" # Agent pid 59566 Теперь осталось добавить сгенерированный ключ в ssh-agent: > ssh-add ~/.ssh/id_rsa Если вы настроите доступ по ssh к своему репозиторию с использованием ключа, то работу, вероятно, можно будет производить и из программ. Для уже созданного репозитория можно изменить способ доступа, используя команду > git remote set-url origin где задаёт путь, в котором используется нужный протокол

понедельник, 25 ноября 2019 г.

Как удалить ветку Git и локально, и удаленно?


Я хочу удалить ветку и локально, и удаленно из проекта на GitHub.

Локально удаляется

> git branch -D feature/experiment
> Deleted branch feature/experiment (was 863225e).


Попытки удалить ветку на сервере

> git branch -d origin/feature/experiment
error: branch 'origin/feature/experiment' not found.
> git branch -rd origin/feature/experiment
Deleted remote branch origin/feature/experiment (was 863225e).
> git pull
* [new branch]      feature/experiment -> origin/feature/experiment


Непонятно, что означает "Deleted remote branch", если на самом деле ветвь не была удалена? Последующая команда pull показывает это.

Что нужно делать, чтобы удалить ветвь и локально, и на сервере?
    


Ответы

Ответ 1



В Git v1.7.0, вы можете удалить удалённую ветку, используя git push origin --delete что легче запомнить, чем git push origin : добавленное в Git v1.5.0 "чтобы удалить удалённую ветку или метку". Оригинал

Ответ 2



Удалить ветку в remote репозитории можно так: git push origin :feature/experiment -rd не работает потому, что он удаляет только локальную remote-tracking ветку. Есл соответствующая ветка на была удалена из remote репозитория, remote-tracking ветка будет создана заново при следующем вызове команды fetch.

вторник, 16 июля 2019 г.

Как удалить метку о удалённой ветке?

Есть удалённое GIT хранилище (original). Есть локальное хранилище (Z) без рабочих файлов. В локальное хранилище Z были сохранены две ветки branch1 и branch2.
Создали две рабочие папки хранилища. Из одной выполнили команду удаления удалённой ветки:
$ git push Z --delete branch1
Теперь, если во второй рабочей папке вывести список удалённых веток, то мы увидим метку branch1:
$ git branch --remote z/branch1 z/branch2 origin/HEAD -> origin/master
Если мы из второй папки попытаемся выполнить команду удаление ветки branch1, то получим сообщение об ошибке:
$ git push Z --delete branch1 error: unable to delete 'branch1': remote ref does not exist error: failed to push some refs to 'Z:\GitRepositories\Storage1'
Как удалить информацию о удалённой ветки branch1 из второй рабочей папки?


Ответ

попробуйте во второй копии обновить remote Z с опцией --prune. это должно удалить информацию об уже несуществующих ветках:
$ git remote update Z --prune

среда, 5 июня 2019 г.

Какие изменения происходят на удаленном сервере при git push?

Если я делаю push из локального репозитория в удаленный, то на удаленном файл полностью изменяется на локальный? Или они сначала сравниваются и заливаются только изменения?


Ответ

Git оперирует не файлами, а коммитами.
Коммит — это «снимок» текущего состояния рабочей области. Он содержит полные версии файлов, а не изменения (также называемые дельтами или патчами).
Подробнее о коммитах: Каким образом git сохраняет изменившуюся строку при коммите?
Или они сначала сравниваются и заливаются только изменения?
Отчасти вы правы: они действительно сначала сравниваются. Для сравнения файлов используется алгоритм Secure Hash Algorithm. Когда вы заливаете (push) очередные коммиты на удаленный сервер, Git сравнивает значение sha1 для каждого объекта. Если в его истории уже есть объект для этого значения, то повторно закачиваться он не будет. Если нет — то будет закачана полная версия этого файла, а точнее, содержащий его объект типа blob.
на удаленном файл
Как уже отметил alexander barakin, ваш удаленный сервер скорее всего типа bare, то есть не содержит файлов в рабочей области (а только внутренние файлы Git-репозитория).

суббота, 1 июня 2019 г.

Клонирование git и push в два репозитория

Создал я локальный репозиторий у себя на компьютере:
cd /path/to/git/repo/ git init --bare --shared
В другом месте тоже инициализировал, с которым работал так, напрямую:
cd /path/to/my/project/ git init echo "Helo" >> hello.txt git add . git commit -m "Init"
Вот теперь я хочу в свой локальный репозиторий сделать пуш:
git remote add origin /path/to/git/repo/ git push origin master
Все хорошо, все отлично. Если запустить эту команду в другой директории, он мне все скопирует, то есть сделает то, что я ожидаю:
cd /path/to/test/dir/ git clone /path/to/git/repo/
Теперь я хочу:
Все свои собранные коммиты запушить на свежий, только что созданный репозиторий в bitbucket.org. Иметь возможность пушить как на битбакет, так и в локальный репозиторий
Что мне нужно сделать, чтобы добиться такого результата?
P.S. Отвечая на вопрос, зачем мне нужен локальный репозиторий. Мне нужно всегда иметь на компьютере копию проекта с учетом всех gitignore. Даже тогда, когда у меня нет интернета. Если есть возможность провернуть это без создания локального репозитория, можете дать совет. Но вопрос, как запушить все коммиты на битбакет и не видеть постоянные сообщения Everything up-to-date и другие, не смотря на то, что на компе у меня лежит целая куча нужных мне коммитов, остается открытым


Ответ

когда вы сделали git init, вы уже создали локальный репозиторий. он находится в под-каталоге .git
файлы же, которые вы создали в этом каталоге (/path/to/my/project/), а затем с помощью git add и git commit «добавили в репозиторий», на самом деле представляют собой лишь рабочую копию содержимого репозитория.
репозиторий может быть и без рабочей копии. создаётся такой репозиторий при использовании опции --bare у команд git clone, git init. фактически вы получаете в таком репозитории то же содержимое, что и в каталоге .git у репозитория с рабочей копией
поэтому создавать ещё одну локальную копию репозитория, как сделали вы в каталоге /path/to/git/repo/, нет необходимости. всё содержимое репозитория, все коммиты, вся история — доступны в любой из копий git-репозитория и без доступа к интернету. и коммиты в эту копию репозитория вы можете делать без доступа к интернету.

а как сделать вторую (третью, десятую) копию репозитория на каком-нибудь удалённом сервере, вы уже знаете:
$ git remote add ... $ git push ...

о том, как одной командой git push отправить изменения сразу в несколько репозиториев, написано, например, здесь и здесь. и по-русски: Отправить изменения в несколько репозиториев одной командой push

понедельник, 1 апреля 2019 г.

Как скачать только папки и файлы без репозитория?

Мне надо просто слить репозиторий, без инициализции гита, без истории изменений, без веток. Просто папки и файлы. Как это сделать?
Проблема состоит в следующем: если делать git clone, то мы выкачиваем ее и всю историю и по сути инициализируем гит. Если сделать git init, git add remote ..., git pull - тоже инициализируем гит в директории. Других способов я не знаю.


Ответ

Вариант А: мелкое (неглубокое, shallow) клонирование, а затем убрать все .git*. Это клонирует репо без истории: git clone --depth=1 git@github.com:xxx/yyy.git Вариант Б: git archive. Это сольёт файлы репо в ZIP'е: git archive --format zip --remote=git@github.com:xxx/yyy.git HEAD

суббота, 9 марта 2019 г.

В чем разница между track, set-upstream-to и set-upstream?

Не могу разобраться в теме "отслеживания веток"
Есть 3 команды которые вроде как выставляют для ветки отслеживание на удаленную ветку:
git branch --track git branch --set-upstream-to git branch --set-upstream
По мне, так они делают одно и тоже. Я не понимаю, зачем тогда их аж 3 штуки?


Ответ

флаг --track можно использовать только при создании новых бранчей
Флаги --set-upstream и --set-upstream-to меняют upstream для уже существующего бранча (если не указан --force). Можно считать --track шорткатом для --set-upstream --force
Новый --set-upstream-to отличается от старого --set-upstream порядком аргументов, что позволяет менять upstream для текущего бранча без явного указания его имени:
git branch --set-upstream-to=origin/master

пятница, 11 января 2019 г.

В каких ветках есть локальные изменения

Как узнать, какие ветки содержат закоммиченные, но ещё не запушенные изменения?


Ответ

примерно так:
$ git branch -vv * master c488ea5 [origin/master: ahead 1, behind 1] 20160210184133 test ffc6775 [origin/test: ahead 1] 20160210183855 test2 ffc6775 [origin/test2: behind 1] 20160210183855 test3 7ff0eab 20160210184754
здесь мы видим, что ветки master, test и test2 «привязаны» к удалённым репозиториям (показано и имя репозитория и ветка «привязки»).
также видно, что ветки master и test отстоят на один коммит каждая «впереди» (ahead 1), а master и test2 «позади» (behind 1) от содержимого удалённого репозитория.

дополнительный вопрос, поднятый в комментариях
Как его сократить только до веток, у которых есть ahead/behind? И как убрать commit message из таблицы?
с помощью опций команды branch, по-моему, никак. можно «порезать» вывод чем-то внешним. например, если доступна программа gnu/sed
$ git branch -vv | sed -rn 's/(: (ahead|behind) [0-9]+[^]]*\]).*/\1/p' * master c488ea5 [origin/master: ahead 1, behind 1] test ffc6775 [origin/test: ahead 1] test2 ffc6775 [origin/test2: behind 1]