你使用git管理你的代码(或其他东西)的次数越多,你的目录结构就越混乱,几年后你可能会得到这样的结果:

├── code
│   ├── blog
│   └── website
├── repos
│   ├── coolproject
│   └── demo
├── repositories
│   └── website
└── src
    ├── foo
    └── project1337

进入全屏模式 退出全屏模式

至少对我来说,这发生了。这些目录中的大多数至少是实际的 git 存储库,但有些不是。显然这是一团糟,如果每个目录都包含几十个存储库,则很难找到合适的存储库。

所以我正在寻找一种更好的方式来组织我的存储库,一位朋友告诉我ghq。 ghq 可以轻松管理所有 git 存储库并同时强制执行有组织的目录结构。如果您使用go您将已经知道目录结构,因为它完全相同。

GitHub 徽标x-motemen/ghq

远程存储库管理变得简单

ghq(1)构建状态[覆盖](https://coveralls.io/ r/motemen/ghq?branchu003dmaster)

姓名

ghq - 管理远程存储库克隆

说明

'ghq' 提供了一种组织远程存储库克隆的方法,就像 go get 一样。当您通过 ghq get 克隆远程存储库时,ghq 会使用远程存储库 URL 的主机和路径在特定根目录(默认为 ~/ghq)下创建一个目录。

$ ghq 获取 https://github.com/x-motemen/ghq

次运行 `git clone https://github.com/x-motemen/ghq ~/ghq/github.com/x-motemen/ghq`

您还可以列出本地存储库(ghq 列表)。

概要

ghq get [-u] [-p] [--shallow] [--vcs <vcs>] [--look] [--silent] [--branch ] [--no-recursive] <repository URL>|<host>/<user>/<project>|<user>/<project>|<project>

ghq 列表 [-p] [-e] [<查询>]

ghq create [--vcs <vcs>] <repository URL>|<host>/<user>/<project>|<user>/<project>|<project&gt

ghq 根 [--all]

命令

得到

在 ghq 根目录下克隆一个远程存储库(参见下面的DIRECTORY STRUCTURES)。如果存储库已经克隆到本地,除非提供'-u'('--update')标志,否则不会发生任何事情,在这种情况下,本地存储库被更新(例如'git pull --ff-only')。您使用“-p”选项,存储库是通过...克隆的

在 GitHub 上查看

安装ghq

安装 ghq 是easy。如果你使用 Linux 发行版,你可以检查你的包管理器是否可以使用 ghq。否则,您还有其他一些选择。您可以从GitHub下载当前版本,或者如果您安装了go,您可以运行go get github.com/motemen/ghq。如果您使用 macOS,您可以运行brew install ghq。要验证您的安装,只需运行:

$ ghq root
/home/max/.ghq

进入全屏模式 退出全屏模式

更改ghq根目录

默认情况下,ghq 将所有 git 存储库组织在~/.ghq中,但这可以在您的~/.gitconfig文件中进行更改。例如,我不喜欢将所有存储库放在像.ghq这样的隐藏目录中。相反,我使用~/repos,因此~/.gitconfig文件中的配置条目如下所示:

[ghq]
  root = ~/repos
  root = ~/go/src

进入全屏模式 退出全屏模式

通过多次定义root=...ghq 使用所有目录来查找存储库。如果您使用 go 这将特别有用,因为它以相同的方式组织存储库,但默认情况下将它们放在~/go/src中。如果您运行ghq list来显示所有存储库,ghq 也会在~/repos~/go/src中查找。

克隆一个新的仓库

您现在必须运行ghq get https://github.com/githubtraining/hellogitworld.git而不是运行git clone https://github.com/githubtraining/hellogitworld.git来签出新存储库,而 ghq 将使用存储库 URL 来创建正确的目录结构:

repos/
└── github.com
    └── githubtraining
        └── hellogitworld
            ├── build.gradle
            ├── fix.txt
            ├── pom.xml
            ├── README.txt
            └ ...

进入全屏模式 退出全屏模式

如果您从不同的服务器和不同的用户克隆更多存储库,ghq 将创建目录以保持一切井井有条。例如,我的~/repos目录的摘录如下所示:

├── aur.archlinux.org
│   └── heluxup
│       └── PKGBUILD
├── git.centralserver.de
│   └── max
│       ├── bachelor-thesis
│       ├── dotfiles
│       ├── fotoallerlei
│       ├── k8s
│       ├── telegram-stickers
│       └── wiki
└ github.com
    ├── ekeih
    │   ├── dwdpollen
    │   ├── FrundenBot
    │   ├── hello-github-actions
    │   ├── heluxup
    │   ├── hetzner-deployment
    │   ├── i3-renameworkspace
    │   ├── icinga2telegram
    │   ├── InfiniteWisdomBot
    │   ├── tado
    │   ├── tado-influxdb
    │   ├── taustakuva
    │   └── webhook
    ├── fluxcd
    │   └── helm-operator
    └── grandchild
        └── arch-cleaner

进入全屏模式 退出全屏模式

ghq look以及它的坏处

就个人而言,我发现这种组织方式已经为 ghq 带来了巨大的好处,但主要优势是 ghq 帮助直接跳转到正确的存储库的方式:

$ pwd
/home/max
$ ghq look hello
$ pwd
/home/max/repos/github.com/githubtraining/hellogitworld

进入全屏模式 退出全屏模式

这样就可以在不同的存储库之间快速切换,而无需知道它们的完整路径。不幸的是,这有一个缺点......进程的当前工作目录是其环境的一部分,并且进程环境不能被其子进程修改。如果您想阅读更多关于此的技术背景,我推荐这个Stack Overflow 答案,它更详细地解释了它。最后,这意味着 ghq 不能真正更改 shell 的当前工作目录......相反,它会在新目录中启动一个新的子 shell。从技术上讲,这是可行的,但我发现每个ghq look ...添加一个额外的嵌套 shell 进程结束退出 shell 意味着返回到前一个 shell,这很烦人。

回复:从 Go更改父 shell 目录

2018 年 12 月 31 日

[

5

](https://stackoverflow.com/questions/53984853/change-parent-shell-directory-from-go/53984896#53984896)

我如何编写一个像 'cd' 一样的 Go 程序?

这在 POSIX 系统上是_不可能的_(即使使用任何其他编程语言)。

因为每个进程,包括父 shell 进程,都有它的_own_ current工作目录。因此cd必须是外壳...

打开完整答案

ghq 的开发者在GitHub issue中建议使用 shell 函数来包装 ghq 来解决这个问题。这种方法可能看起来有点奇怪,但实际上效果很好,并且可能是通过运行cd来真正更改当前工作目录的唯一解决方案,它是一个 shell 内置程序(shell 内置程序直接在 shell 进程中运行,而不是在新进程中,因此他们可以修改shell进程的环境)。

GitHub 徽标#29 评论

[!

motemen 评论于2014 年 8 月 19 日

我愿意,但我不认为 ghq 可以更改 shell 的工作目录,因为它只是一个命令,而不是 shell 函数。有什么想法可以实现吗?

一种解决方案是提供一个 shell 函数,例如:

ghq () {

如果 [ "$1" \u003d 看 -a -n "$2" ];然后

cd $(命令 ghq list -e -p $2)

返回

命令 ghq "$@"

}

进入全屏模式 退出全屏模式

在 GitHub 上查看

我稍微扩展了功能并将其添加到我的~/.bashrc中:

ghq () {
  if [ "$1" = look -a -n "$2" ]; then
    local repos=($(command ghq list -p "$2"))
    case ${#repos[@]} in
      0)
        echo 'No repo found.'
        return 1
        ;;
      1)
        cd "${repos[0]}"
        return
        ;;
      *)
        local PS3="Select repo: "
        select reponame in ${repos[@]}; do
          cd "${reponame}"
          return
        done
    esac
  elif [ "$1" = get -a -n "$2" ]; then
    command ghq "$@"
    cd $(command ghq list -e -p "$2")
    return
  fi
  command ghq "$@"
}

进入全屏模式 退出全屏模式

请记住在修改~/.bashrc后打开一个新的 shell 或运行source ~/.bashrc以加载更改。那么它有什么作用呢?每次运行ghq时,您的 shell 不会直接运行真正的 ghq 二进制文件(例如在/usr/bin/ghq中),而是运行具有相同名称的ghqshell 函数。

第 2-19 行包装了ghq look ...调用,这意味着当您调用ghq look foobar时,该函数会搜索名称中包含 foobar 的存储库,如果找到恰好一个,则运行cd ...以切换到它的目录。如果多个存储库匹配_foobar_,它会提供一个选择,然后切换到选定的存储库。

$ ghq look foobar
No repo found.
$ ghq look fotoallerlei
$ pwd
/home/max/repos/git.centralserver.de/max/fotoallerlei
$ ghq look heluxup
1) /home/max/repos/aur.archlinux.org/heluxup
2) /home/max/repos/github.com/ekeih/heluxup
Select repo: 2
$ pwd
/home/max/repos/github.com/ekeih/heluxup

进入全屏模式 退出全屏模式

第 20-25 行包装了ghq get ...调用以在成功克隆后切换到新存储库。如果 ghq 既没有使用look也没有使用get调用,则直接调用原始 ghq 二进制文件。

总结

将我现有的存储库移动到 ghq 的目录结构后,我开始每天都使用它。我花了几天时间才记住使用ghq get ...而不是git clone ...ghq look ...而不是cd ~/repos/...,但是我非常喜欢这个新的工作流程,并且可以将它推荐给使用多个 git 存储库的每个人。用于包装 ghq 调用以避免嵌套 shell 进程的 shell 函数使其更易于使用,因此,如果您开始使用 ghq,请花点时间将其添加到您的~/.bashrc

Logo

更多推荐