git clone后如何自动CD?


35

我想在输入某些内容后自动cd进入clone命令创建的目录git clone

重要提示:我不想更改命令的语法(例如,使用别名/函数),因为它会破坏我从Pretzo项目中自动获得的zsh完成。

编辑:之所以没有选择正确的答案,是因为没有给出符合上述条件的答案。

我使用ZSH,但在其他外壳程序中的答案也是可以接受的。


我喜欢unix.stackexchange.com/questions/97920/…的答案,但是它需要提及在~/.bashrc文件上写入该功能(例如),至少对我来说它不起作用,我需要用替换该功能来修复它。线路:/usr/bin/git "$@" 2>&1 | tee $tmp
lcestari,2015年

Answers:


19

创建一个函数:

gclonecd() {
  git clone "$1" && cd "$(basename "$1" .git)"
}

(适用于带有和不带有“ .git”的链接)


2
我想继续使用,git clone因为如果不使用,我将不得不更改所有工具git集线器的别名为git,oh-my-zsh提供自动完成功能,等等...
Daniel

3
@Wildeyes git无法更改外壳程序的工作目录,因此无论哪种方式,您都必须将其包装在一个别名/函数中,该别名/函数可以执行您想要的操作,并通过内置函数进行处理cd。如果要调用hub而不是git,请在函数中进行调用。如果希望它仅影响clone命令,请检查函数中的操作。等等
frostschutz

我注意到生成basename git@github.com:pckujawa/pattern-rec.gitpattern-rec.git的结果-克隆时是否只保留了.git扩展名?
2014年

8
@Pat basename也带有后缀参数,因此您可以执行以下操作:git clone $1 && cd $(basename $1 .git)
Henrik N

17

git clone需要一个附加参数:要使用的目录。您可以使用使其克隆到当前工作目录中,git clone URL . 然后,无需更改工作目录。你已经在那里。

如果您确实希望git命令实际更改工作目录,则可以将其更改为git在必要时调用real的函数:

git()
{
   local tmp=$(mktemp)
   local repo_name

   if [ "$1" = clone ] ; then
     /usr/bin/git "$@" | tee $tmp
     repo_name=$(awk -F\' '/Cloning into/ {print $2}' $tmp)
     rm $tmp
     printf "changing to directory %s\n" "$repo_name"
     cd "$repo_name"
   else
     /usr/bin/git "$@"
   fi
}

那正是我想要的。在意识到没有内部钩子之类的东西之后,我写了一个几乎准确的函数:)
Daniel K.

2
@Wildeyes是的:有一个/tmp在RAM中的卷,就像任何现代Linux通过tmpfs所做的一样。无论如何,当您刚刚完成git clone(它会创建目录并将数百个文件写入磁盘)时,为什么还要关心写入磁盘呢?
Kaz 2013年

1
您可能对整个“ nvm,如果它写入磁盘”是正确的,我只是想节省额外的操作。非常感谢Kaz。
Daniel K.

3
小心。是git [flags] command [arguments],所以盲目要求clone在某个位置将失败。
vonbrand '16

1
添加“真实”路径会有所帮助吗?就像:git_real_home = which git git(){... $ git_real_home“ $ @” | tee $ tmp
aakoch

7

如果提供仓库的本地名称,使用$ _真的很容易:

git clone git@github.com:npm/npm.git npm-local-dir && cd $_

但是,如果您不想重新输入长名称,那么使用sed可能有点丑陋但可行:

git clone git@github.com:pckujawa/pattern-rec.git && 
cd `echo $_ | sed -n -e 's/^.*\/\([^.]*\)\(.git\)*/\1/p'`

编辑:好吧,我要感谢马纳夫(下面的评论)的简洁

git clone foo/bar && cd !$:t

但它在zsh中不起作用(有关zsh如何进行扩展的内容导致它不会将第一个命令视为输入!$)。我不得不查看做了什么!$:t在Bash Shell中前进| $ {me:-whatever})。!$抓取上一个命令的最后一部分,然后:t将“删除所有开头的文件名组件,不留尾巴。” 很好的信息,但是我希望我可以将其与zsh一起使用(我尝试noglob没有成功)。

编辑:而不是使用sed!$:t(无论如何对我来说都不在zsh中起作用),我发现了另外两个选项(一个使用https调整了https://unix.stackexchange.com/users/5685/frederik-deweerdt的答案)://unix.stackexchange.com/users/129926/henrik-n的评论):

git clone git@github.com:npm/npm.git && cd $(basename $_ .git)

要么

git clone git@github.com:npm/npm.git && cd ${${_%%.git*}##*/}

git clone foo/bar && cd !$:t
Manav 2015年

如果您的回购网址以结尾,则.git可以使用!$:t:r来获取文件夹名称。
Michael Stramel

2

任何POSIX Shell的简单解决方案是指定要克隆到的目录(任何文件系统路径),然后将其重用:

git clone <repository> <directory> &&
cd "$_"

cd -

完成后。


2

您可以执行以下操作:

clone_check() {
  (($? != 0)) && return
  local cmd=$history[$((HISTCMD-1))]
  cmd=("${(@Q)${(z)cmd}}")
  if [[ $cmd = "git clone "* ]]; then
    local dir
    if (($#cmd == 3)); then
      dir=${cmd[3]:t}
      dir=${dir%.git}
      dir=${dir#*:}
    elif (($#cmd > 3)); then
      dir=$cmd[-1]
    else
      return
    fi
    print -r CDing into $dir > /dev/tty
    cd -- $dir
  fi
}
precmd_functions+=(clone_check)

这是非常简单的。它是一个precmd钩子(在每个提示符之前执行),检查最后一个命令行是git clone .../something还是git clone .../something dir,然后从中猜测目录并CD进入目录。

如果您输入git clone foo; whateverwhatever; git clone foogit clone --option repo...


+1非常感谢您提供的代码;我从几天开始使用它。我刚刚注意到一个问题。如果在克隆某些项目后立即关闭终端,则下次打开终端时,zsh会显示两个错误消息:CDing into <project>clone_check:cd:17: no such file or directory: <project>。一旦您在关闭终端之前运行的最后一个命令不同于,该错误就会消失$ git clone
user938271

2

这是上述答案的改编 OSX

  • mktemp 需要其他参数
  • git cloneSTDERR在默认情况下(见

功能:

function git {
   local tmp=$(mktemp -t git)
   local repo_name

   if [ "$1" = clone ] ; then
     command git "$@" --progress 2>&1 | tee $tmp
     repo_name=$(awk -F\' '/Cloning into/ {print $2}' $tmp)
     rm $tmp
     printf "changing to directory %s\n" "$repo_name"
     cd "$repo_name"
   else
     command git "$@"
   fi
}

1
有7个答案显示您的“之上”。但是它可能会随着时间而改变。这些参考在SE上没有意义,请编辑您的答案,并包含指向您所参考答案的链接。
techraf '16

0

我不推荐使用,但您可以使用以下这种单线:

echo 'project' | xargs -I % sh -c 'git clone https://github.com/username/%.git && cd %'


0

包括在您的外壳中:

git(){
  case "$1" in clone) git-clone "${@:2}";; *) command git "$@";; esac
}
git-clone(){ 
   local tgt 
   tgt=$(command git clone "$@" 2> >(tee /dev/stderr |head -n1 | cut -d \' -f2)) ||
      return $?
   cd "$tgt"
}

通过从git的标准错误中无意地收集克隆目标,并cd在(且仅当)克隆成功的情况下将目标插入目标中,才能工作。

它接受常规所接受的所有参数和选项git clone

您既可以使用git包装器,而不必担心完成情况,也可以摆脱git包装器,然后将git clone完成情况重新连接到git-clone

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.