Использование разветвленного импорта пакетов в Go

105

Предположим, у вас есть репозиторий, на github.com/someone/repoкоторый вы сделали форк github.com/you/repo. Вы хотите использовать свою вилку вместо основного репо, поэтому вы делаете

go get github.com/you/repo

Теперь все пути импорта в этом репо будут «сломаны», то есть если в репозитории есть несколько пакетов, которые ссылаются друг на друга через абсолютные URL-адреса, они будут ссылаться на источник, а не на вилку.

Есть ли лучший способ клонировать его вручную на правильный путь?

git clone git@github.com:you/repo.git $GOPATH/src/github.com/someone/repo
Эрик Айгнер
источник
1
Никакой путь импорта в новом форке не будет нарушен, если он не был нарушен еще до разветвления.
zzzz
11
Извините, что разочаровал вас, но это неправда. Если субпакет упоминается в импорте через его абсолютный URL-адрес, этот импорт будет прерван в вилке (или, по крайней мере, будет ссылаться на неправильный пакет).
Эрик Айгнер
2
Например, гоамз . У него есть внутренние ссылки повсюду.
Эрик Айгнер,
1
Посмотри на ec2пакет - launchpad.net/goamz/awsимпортный. И пакеты , awsи ec2пакеты находятся в ОДНОМ репозитории, поэтому при разветвлении не будут ссылаться на правильный пакет (тот, что находится в вилке).
Эрик Айгнер
1
Вилка будет ссылаться на тот же пакет, что и исходный код вилки. Что в этом неправильного? Форк будет скомпилирован, он будет построен и будет делать то же самое, что и раньше. Что же тогда означает «неправильный пакет»? Обратите внимание , что язык Go, так как его система сборки, не имеет не понимания хранилищ, только пакеты.
zzzz

Ответы:

85

Для обработки запросов на вытягивание

  • разветвить репозиторий github.com/someone/repoнаgithub.com/you/repo
  • скачать исходный код: go get github.com/someone/repo
  • будь там: cd "$(go env GOPATH)/src"/github.com/someone/repo
  • разрешить загрузку на вилку: git remote add myfork https://github.com/you/repo.git
  • загрузите свои изменения в свое репо: git push myfork

http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html

Чтобы использовать пакет в своем проекте

https://github.com/golang/go/wiki/PackageManagementTools

Иван Рейв
источник
из какой папки делать git remote add? клон с вилки? клон из оригинала? изнутри идти?
лапоты
1
@lapots запускают команду в исходном репо (то есть $ GOPATH / src / github.com / somone / repo)
will7200
Что, если я хочу внести изменения в репо, которое было разветвлено давно?
NA
64

Если вы используете модули go . Вы можете использовать replaceдирективу

replaceДиректива позволяет поставить другой путь импорта , который может быть другой модуль , расположенный в VCS (GitHub или в другом месте), или в локальной файловой системе с относительным или абсолютным путем к файлу. Новый путь импорта из replaceдирективы используется без необходимости обновлять пути импорта в фактическом исходном коде.

Итак, вы можете сделать ниже в своем файле go.mod

module github.com/yogeshlonkar/openapi-to-postman

go 1.12

require (
    github.com/someone/repo v1.20.0
)

replace github.com/someone/repo => github.com/you/repo v3.2.1

где v3.2.1тег на вашем репо. Также можно сделать через CLI

go mod edit -replace="github.com/someone/repo@v0.0.0=github.com/you/repo@v1.1.1"
Йогеш
источник
4
отлично работал. Я думаю, единственная причина, по которой у этого нет большего количества голосов, заключается в том, что люди еще не используют модули go. Я также использовал этот трюк, чтобы указать местоположение файла в другом каталоге на моей рабочей станции, где у меня были локальные изменения, над которыми я работал. Я бы просто удалил свою строку «заменить», как только я внесу свои локальные изменения в github.
lazieburd
^ Согласен на 100%. Голосуйте народ.
Эндрю Эрроу
2
ой, но "хозяин" у меня не работал. Пришлось написать туда v0.0.1 или какую-то конкретную версию.
Эндрю Эрроу
1
Вы можете также go mod edit -replace непосредственно в командной строке: go mod edit -replace="github.com/someone/repo@v0.0.0=github.com/you/repo@v1.1.1". Оба варианта @v...не обязательны.
Джоэл Purra
Разве не было бы здорово иметь go.mod.localили, go.mod.devчья роль состоит в том, чтобы фактически заменить путь импорта для локальной разработки? Я имею в виду, что вы никогда не забудете удалить уродливую «замену», потому что вам не придется этого делать.
Мануэль
21

Один из способов ее решения - предложенный Иваном Рейвом и http://blog.campoy.cat/2014/03/github-and-go-forking-pull-requests-and.html способ разветвления.

Другой - обойти поведение golang . Когда вы go get, golang размещает ваши каталоги под тем же именем, что и в URI репозитория, и здесь начинаются проблемы.

Если вместо этого вы создадите свой собственный git clone, вы можете клонировать свой репозиторий в свою файловую систему по пути, названному в честь исходного репозитория.

Предполагая, что исходный репозиторий есть github.com/awsome-org/toolи вы его разместили github.com/awesome-you/tool, вы можете:

cd $GOPATH
mkdir -p {src,bin,pkg}
mkdir -p src/github.com/awesome-org/
cd src/github.com/awesome-org/
git clone git@github.com:awesome-you/tool.git # OR: git clone https://github.com/awesome-you/tool.git
cd tool/
go get ./...

golang совершенно счастлив продолжить работу с этим репозиторием и на самом деле не заботится о том, чтобы какой-то верхний каталог имел имя, awesome-orgа git remote awesome-you. Весь импорт для awesome-orgвозобновляется через только что созданный каталог, который является вашим локальным рабочим набором.

Более подробно см. Мое сообщение в блоге: Разветвление репозиториев Golang на GitHub и управление путем импорта

изменить : фиксированный путь к каталогу

Шломи Ноах
источник
3
Я согласен, что это «лучшее» решение для этого. Но было бы действительно приятно увидеть, как люди управляют этим рабочим процессом при запуске приложения Go в контейнере Docker. Я изучаю golang и хотел добавить крошечную функцию в библиотеку, которую использую, когда столкнулся с этой головной болью при тестировании перед созданием запроса на слияние.
Joakim
6

Если ваш форк носит временный характер (то есть вы намереваетесь его объединить), просто выполняйте разработку на месте, например, в $GOPATH/src/launchpad.net/goamz.

Затем вы используете функции системы контроля версий (например git remote), чтобы сделать исходный репозиторий вашим репозиторием, а не исходный.

Это усложняет другим людям использование вашего репозитория, go getно намного упрощает его интеграцию в исходный код.

На самом деле у меня есть репозиторий для goamz, для lp:~nick-craig-wood/goamz/goamzкоторого я разрабатываю именно так. Может, автор когда-нибудь сольет!

Ник Крейг-Вуд
источник
1
Просто чтобы я понял последствия этого, если я пошел по этому маршруту, когда кто-то сделает go getиз моего репо, все мои операторы импорта и тому подобное по-прежнему будут отражаться github.com/original_authorи, таким образом, будут нарушены ... правильно?
parker.sikand
@ parker.sik и да, это правильно. Этот метод лучше всего подходит для вещей, которые вы собираетесь объединить в восходящем потоке, а не для использования на практике. Если вы намереваетесь разветвлять пакет навсегда, используйте другой способ ответа.
Ник Крейг-Вуд
4

Вот способ, который подходит всем:

Используйте github для создания ответвления на «my / repo» (просто пример):

go get github.com/my/repo
cd ~/go/src/github.com/my/repo
git branch enhancement
rm -rf .
go get github.com/golang/tools/cmd/gomvpkg/…
gomvpkg <<oldrepo>> ~/go/src/github.com/my/repo
git commit

Повторяйте каждый раз, когда будете улучшать код:

git commit
git checkout enhancement
git cherry-pick <<commit_id>>
git checkout master

Зачем? Это позволяет вам иметь репо, с которым go getработает любой . Он также позволяет поддерживать и улучшать ветку, подходящую для запроса на вытягивание. Он не набивает git словом «vendor», он сохраняет историю, и инструменты сборки могут понять ее.

user1212212
источник
Небольшое исправление: запустите github.com/golang/tools/cmd/gomvpkg/main.go, и эта команда переместит .git, поэтому сохраните его в другом месте и восстановите его позже.
user1212212
также можно просто использовать плагин mvn-golang, который делает некоторую автоматизацию обработки зависимостей, как в примере github.com/raydac/mvn-golang/tree/master/mvn-golang-examples/…
Игорь Мазница
3

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

Джереми Уолл
источник
3
Я потратил больше времени, чем хотел бы признать, диагностировав это в моем первом вкладе в проект Go. «Все тесты проходят успешно, в том числе и те, которые я написал для исчерпывающего тестирования новой функциональности. Что случилось ?!» Известны ли вам какие-либо доступные инструменты, чтобы облегчить эту проблему для новичков?
Сейдж Митчелл
3
Как только я понял, что это было легко решить, используя find, xargsи sed, но это помогло бы иметь безболезненный рабочий процесс, который последовательно работает для всех.
Сейдж Митчелл
@JakeMitchell gomvpkgможет сделать переименование проще / лучше. go get golang.org/x/tools/cmd/gomvpkgтогда gomvpkg -help.
Dave C
3
Этот ответ кажется мне совершенно непрактичным. Удаление файлов проекта из разветвленного проекта, это безумие? Что вы делаете, когда создаете пул-реквест? Мне кажется, что ответ Ивана Рейва гораздо лучше.
Иван П,
8
Это все еще то, как Go-lang работает? Это настолько безумие, что это не смешно ... Либо подходите к восходящему потоку, либо к нисходящему потоку, но не то и другое вместе. По моему не столь скромному мнению, это огромный недостаток дизайна, вероятно, сделанный людьми, которые не участвуют в большом количестве кросс-проектов. #FAIL #GOLANG
Никлас Хедман
1

Чтобы автоматизировать этот процесс, я написал небольшой скрипт. Вы можете найти более подробную информацию в моем блоге, чтобы добавить команду типа "gofork" в ваш bash.

function gofork() {
  if [ $# -ne 2 ] || [ -z "$1" ] || [ -z "$2" ]; then
    echo 'Usage: gofork yourFork originalModule'
    echo 'Example: gofork github.com/YourName/go-contrib github.com/heirko/go-contrib'
    return
  fi
   echo "Go get fork $1 and replace $2 in GOPATH: $GOPATH"
   go get $1
   go get $2
   currentDir=$PWD
   cd $GOPATH/src/$1
   remote1=$(git config --get remote.origin.url)
   cd $GOPATH/src/$2
   remote2=$(git config --get remote.origin.url)
   cd $currentDir
   rm -rf $GOPATH/src/$2
   mv $GOPATH/src/$1 $GOPATH/src/$2
   cd $GOPATH/src/$2
   git remote add their $remote2
   echo Now in $GOPATH/src/$2 origin remote is $remote1
   echo And in $GOPATH/src/$2 their remote is $remote2
   cd $currentDir
}

export -f gofork
Heralight
источник
Следует golangизменить на goforkв строке 4?
Дэн Тененбаум
хорошо видно! исправить!
heralight
1

Совместное использование вендоров и подмодулей

  1. Создайте вилку библиотеки на github (в данном случае go-mssqldb)
  2. Добавьте подмодуль, который клонирует вашу вилку в папку вашего поставщика, но имеет путь к исходному репо
  3. Обновите свой import операторы в исходном коде, чтобы они указывали на папку поставщика (без vendor/префикса). Например vendor/bob/lib=>import "bob/lib"

Например

cd ~/go/src/github.com/myproj

mygithubuser=timabell
upstreamgithubuser=denisenkom
librepo=go-mssqldb

git submodule add "git@github.com:$mygithubuser/$librepo" "vendor/$upstreamgithubuser/$librepo"

Зачем

Это решает все проблемы, о которых я слышал и сталкивался, пытаясь понять это сам.

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

Больше информации

Тим Абелл
источник
0

в свой Gopkg.tomlфайл добавьте эти блоки ниже

[[constraint]]
  name = "github.com/globalsign/mgo"
  branch = "master"
  source = "github.com/myfork/project2"

Таким образом, он будет использовать вилку project2вместоgithub.com/globalsign/mgo

msonowal
источник
Используется Gopkg.tomlтолько файл, depкоторый в этом вопросе вообще не упоминается. Новые проекты Go должны вместо этого использовать модули Go (и существующие проекты IMO, основанные на dep, также должны быть перенесены).
Dave C
Я не знал об этой функции деп, и ваш ответ наверняка мне помог :)
Вегер
0

Вы можете использовать команду, go get -fчтобы получить разветвленное репо

Кевин
источник