Làm thế nào để cd tự động sau khi git clone?


37

Tôi muốn tự động cdvào thư mục được tạo bởi clonelệnh sau khi tôi làm git clonegì đó.

Quan trọng: Tôi không muốn thay đổi cú pháp cho lệnh (ví dụ: sử dụng bí danh / hàm) vì nó sẽ phá vỡ các hoàn thành zsh mà tôi nhận được tự động từ Pretzodự án.

EDIT : Lý do tôi không chọn bất kỳ câu trả lời nào là đúng, là vì không có câu trả lời nào được đưa ra mà không tuân thủ các điều kiện trên.

Tôi sử dụng ZSH, nhưng một câu trả lời trong bất kỳ shell nào khác cũng được chấp nhận.


Tôi thích câu trả lời unix.stackexchange.com/questions/97920/, nhưng cần phải đề cập đến việc viết chức năng đó trên ~/.bashrctệp (ví dụ) và đối với tôi ít nhất nó không hoạt động, tôi cần sửa nó bằng cách thay thế dòng:/usr/bin/git "$@" 2>&1 | tee $tmp
leopari

Câu trả lời:


19

Tạo một chức năng:

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

(Hoạt động cho các liên kết cả có và không có ".git")


2
Tôi muốn tiếp tục sử dụng git clonevì tất cả các công cụ mà tôi sẽ phải thay đổi nếu tôi không sử dụng git. Hub được đặt bí danh là git, oh-my-zsh cung cấp tự động hoàn thành, v.v ...
Daniel K.

3
@Wildeyes gitkhông thể thay đổi thư mục làm việc của trình bao của bạn, vì vậy, bằng cách nào đó, bạn sẽ phải bọc nó trong một bí danh / hàm thực hiện những gì bạn muốn và theo dõi nó với nội dung cd. Nếu bạn muốn gọi hubthay vì git, hãy làm như vậy trong chức năng. Nếu bạn muốn nó chỉ ảnh hưởng đến clonelệnh, hãy kiểm tra hành động trong hàm. vv
frostschutz

Tôi nhận thấy rằng basename git@github.com:pckujawa/pattern-rec.gitkết quả trong mẫu-rec.git - bạn có bỏ phần mở rộng .git khi sao chép không?
Pat

8
@Pat basenamecũng có một đối số hậu tố, vì vậy bạn có thể làm:git clone $1 && cd $(basename $1 .git)
Henrik N

17

git clonemất một đối số bổ sung: thư mục để sử dụng. Bạn có thể làm cho nó sao chép vào thư mục làm việc hiện tại với git clone URL . Then, không cần thay đổi thư mục làm việc; bạn đã ở đó

Nếu bạn thực sự muốn gitlệnh thực sự thay đổi thư mục làm việc, bạn có thể thay đổi nó thành một hàm gọi thực gitkhi cần thiết:

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
}

Đó chính xác là những gì tôi đang tìm kiếm. Sau khi tôi nhận ra không có móc bên trong hoặc thứ gì đó tương tự, tôi đã viết một chức năng gần như chính xác :)
Daniel K.

2
@Wildeyes Có: có /tmpâm lượng trong RAM, giống như bất kỳ Linux hiện đại nào thông qua tmpfs. Dù sao, tại sao bạn lại quan tâm đến việc ghi vào đĩa, khi bạn vừa thực hiện một bản sao git, tạo thư mục và ghi hàng trăm tệp vào đĩa ...
Kaz

1
Bạn có thể đúng về toàn bộ điều "nvm nếu nó ghi vào đĩa", tôi chỉ tìm cách lưu các hoạt động bổ sung. Cảm ơn rất nhiều Kaz.
Daniel K.

3
Hãy cẩn thận. đó là git [flags] command [arguments], vì vậy mù quáng yêu cầu cloneở vị trí nhất định sẽ thất bại.
vonbrand

1
Sẽ thêm đường dẫn "thực sự" giúp đỡ? Giống như: git_real_home = which git git () {... $ git_real_home "$ @" | tee $ tmp
aakoch

7

Nếu bạn cung cấp tên địa phương của repo, việc sử dụng $ _ : thực sự dễ dàng

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

Nhưng nếu bạn không muốn gõ lại tên dài, thì hơi xấu nhưng có thể thực hiện được với sed:

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

EDIT: Vâng, tôi sẽ cảm ơn Manav (bình luận bên dưới) cho terse

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

nhưng nó không hoạt động trong zsh (một cái gì đó về cách zsh mở rộng khiến nó không coi lệnh đầu tiên là đầu vào !$). Tôi đã phải tìm kiếm những gì !$:tđã làm ( Tiến lên trong Bash Shell | $ {me: -whthing} ). !$lấy phần cuối của lệnh trước đó và :tsẽ "Xóa tất cả các thành phần tên tệp hàng đầu, để lại phần đuôi". Thông tin tốt, nhưng tôi ước tôi có thể làm cho nó hoạt động với zsh (Tôi đã cố gắng noglobkhông thành công).

EDIT: Thay vì sử dụng sedhoặc !$:t(không hoạt động trong zsh, dù sao đối với tôi), tôi đã tìm thấy hai tùy chọn khác (một điều chỉnh https://unix.stackexchange.com/users/5685/frederik-deweerdt 's trả lời bằng https : //unix.stackexchange.com/users/129926/henrik-n 's bình luận):

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

hoặc là

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

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

Nếu url repo của bạn kết thúc, .gitbạn có thể sử dụng !$:t:rđể lấy tên thư mục.
Michael Stramel

2

Một giải pháp đơn giản cho mọi trình bao POSIX là chỉ định thư mục sao chép một cách rõ ràng (bất kỳ đường dẫn hệ thống tệp nào) và sử dụng lại:

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

cd -

khi bạn hoàn thành


2

Bạn có thể làm một cái gì đó như:

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)

Nó khá đơn giản. Đó là một precmdcái móc (thực hiện trước mỗi cửa sổ), mà kiểm tra xem dòng lệnh cuối cùng trông giống như git clone .../somethinghoặc git clone .../something dir, đoán thư mục từ đó và cd vào nó.

Nó không hoạt động nếu bạn nhập git clone foo; whateverhoặc whatever; git clone foohoặc git clone --option repo...


+1 Cảm ơn bạn rất nhiều về mã; Tôi đang sử dụng nó từ một vài ngày. Tôi vừa nhận thấy một vấn đề; nếu bạn đóng thiết bị đầu cuối ngay sau khi nhân bản một số dự án, lần sau khi bạn mở một thiết bị đầu cuối, zsh sẽ phàn nàn với hai thông báo lỗi: CDing into <project>clone_check:cd:17: no such file or directory: <project>. Lỗi biến mất ngay sau khi lệnh cuối cùng bạn chạy trước khi đóng thiết bị đầu cuối khác với $ git clone.
dùng938271

2

Đây là một bản phóng tác của câu trả lời trên cho OSX

  • mktemp yêu cầu tham số bổ sung
  • git cloneghi vào STDERRmặc định (xem cái này )

Chức năng:

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
Có 7 câu trả lời hiển thị "bên trên" của bạn. Nhưng nó có thể thay đổi theo thời gian. Các tài liệu tham khảo như vậy không có ý nghĩa gì về SE, vui lòng chỉnh sửa câu trả lời của bạn và bao gồm một liên kết đến câu trả lời mà bạn đang đề cập.
techraf

0

Tôi sẽ không đề xuất nó, nhưng bạn có thể sử dụng một lớp lót này:

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


0

Bao gồm điều này trong vỏ của bạn:

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"
}

Điều này hoạt động bằng cách lén lút lượm lặt mục tiêu nhân bản từ lỗi tiêu chuẩn của git và cd'xâm nhập vào mục tiêu nếu (và chỉ khi) nhân bản thành công.

Nó chấp nhận tất cả các đối số và tùy chọn mà thông thường git clonelàm.

Hoặc bạn có thể sử dụng trình bao bọc git và không phải lo lắng về việc hoàn thành của mình hoặc bạn có thể thoát khỏi trình bao bọc git và sắp xếp lại các git clonehoàn thành của bạn git-clone.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.