วิธี cd โดยอัตโนมัติหลังจาก git clone?


35

ฉันต้องการcdไดเรกทอรีที่สร้างขึ้นโดยcloneคำสั่งโดยอัตโนมัติหลังจากที่ฉันทำgit cloneบางสิ่งบางอย่าง

สำคัญ:ฉันไม่ต้องการแก้ไขไวยากรณ์สำหรับคำสั่ง (เช่นใช้นามแฝง / ฟังก์ชั่น) เพราะมันจะทำลาย zsh-completions ที่ฉันได้รับโดยอัตโนมัติจากPretzoโครงการ

แก้ไข : เหตุผลที่ฉันไม่ได้เลือกคำตอบที่ถูกต้องเป็นเพราะไม่มีคำตอบที่ได้ปฏิบัติตามเงื่อนไขข้างต้น

ฉันใช้ ZSH แต่คำตอบในเชลล์อื่น ๆ ก็เป็นที่ยอมรับเช่นกัน


ฉันชอบคำตอบunix.stackexchange.com/questions/97920/ …แต่ต้องพูดถึงการเขียนฟังก์ชั่นนั้นใน~/.bashrcไฟล์ (ตัวอย่าง) และสำหรับฉันอย่างน้อยมันก็ไม่ทำงานฉันต้องแก้ไขมันด้วยการแทนที่ บรรทัด:/usr/bin/git "$@" 2>&1 | tee $tmp
lcestari

คำตอบ:


19

สร้างฟังก์ชั่น:

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

(ใช้ได้สำหรับลิงก์ทั้งที่มีและไม่มี ".git")


2
ผมอยากจะให้ใช้เพราะทุกเครื่องมือที่ผมจะต้องเปลี่ยนแปลงถ้าฉันไม่ได้ใช้git clone Hubเป็นนามแฝงว่าคอมไพล์ oh-my-zsh นำเสนอการเติมข้อมูลอัตโนมัติ ฯลฯ ...git
Daniel K.

3
@Wildeyes gitไม่สามารถเปลี่ยนไดเร็กตอรี่การทำงานของเชลล์, ดังนั้นคุณจะต้องห่อมันด้วย alias / function ที่ทำในสิ่งที่คุณต้องการและตามด้วย builtin cd. หากคุณต้องการโทรhubแทนgitให้ทำในฟังก์ชั่น หากคุณต้องการให้มันมีผลกับcloneคำสั่งเท่านั้นให้ตรวจสอบการกระทำในฟังก์ชั่น ฯลฯ
frostschutz

ฉันสังเกตเห็นว่าbasename git@github.com:pckujawa/pattern-rec.gitผลลัพธ์เป็น pattern-rec.git คุณเพิ่งออกจากส่วนขยาย. git เมื่อคุณโคลนหรือไม่
Pat

8
@Pat basenameใช้อาร์กิวเมนต์ต่อท้ายด้วยดังนั้นคุณสามารถทำได้:git clone $1 && cd $(basename $1 .git)
Henrik N

17

git cloneใช้อาร์กิวเมนต์เพิ่มเติม: ไดเรกทอรีที่จะใช้ คุณสามารถทำให้มันโคลนในไดเรกทอรีการทำงานปัจจุบันด้วยgit clone URL . จากนั้นไม่จำเป็นต้องเปลี่ยนไดเรกทอรีการทำงาน; คุณอยู่ที่นั่นแล้ว

หากคุณต้องการให้gitคำสั่งเปลี่ยนไดเรกทอรีทำงานจริง ๆ คุณสามารถเปลี่ยนเป็นฟังก์ชันที่เรียกจริงgitเมื่อจำเป็น:

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
}

นั่นคือสิ่งที่ฉันกำลังมองหา หลังจากที่ฉันตระหนักไม่มีตะขอภายในหรือสิ่งที่ต้องการที่ผมเขียนฟังก์ชั่นเกือบแน่นอน :)
แดเนียลเค

2
@Wildeyes ใช่: มี/tmpไดรฟ์ข้อมูลที่อยู่ใน RAM เหมือนกับ Linux สมัยใหม่ใด ๆ ที่ทำผ่าน tmpfs อย่างไรก็ตามทำไมคุณสนใจที่จะเขียนแผ่นดิสก์เมื่อคุณเพิ่งทำโคลนคอมไพล์ซึ่งสร้างไดเรกทอรีและเขียนไฟล์หลายร้อยไฟล์ลงบนดิสก์ ...
Kaz

1
คุณอาจถูกต้องเกี่ยวกับ "nvm ทั้งหมดถ้ามันเขียนลงดิสก์" ฉันแค่ต้องการบันทึกการดำเนินการพิเศษ ขอบคุณมาก Kaz
Daniel K.

3
ระวัง. มันคือการgit [flags] command [arguments]สุ่มสี่สุ่มห้าcloneในบางตำแหน่งจะล้มเหลว
vonbrand

1
จะเพิ่มความช่วยเหลือเส้นทาง "ของจริง" หรือไม่ ไลค์: git_real_home = which git git () {... $ git_real_home "$ @" | tee $ tmp
aakoch

7

หากคุณให้ชื่อท้องถิ่นของ repo มันง่ายมากที่จะใช้$ _ :

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'`

แก้ไข: ดีฉันจะขอบคุณ Manav (ความคิดเห็นด้านล่าง) สำหรับบทกวี

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

แต่มันใช้งานไม่ได้ใน zsh (บางอย่างเกี่ยวกับวิธีที่ zsh ขยายเพิ่มทำให้ไม่ต้องใช้คำสั่งแรกเป็นอินพุต!$) ฉันต้องค้นหาสิ่งที่!$:tทำ ( ล้ำหน้าใน Bash Shell | $ {me: -whething} ) !$คว้าส่วนสุดท้ายของคำสั่งก่อนหน้านี้และ:tจะ "ลบองค์ประกอบชื่อไฟล์ชั้นนำทั้งหมดออกจากส่วนท้าย" ข้อมูลที่ดี แต่ฉันหวังว่าฉันจะสามารถใช้งาน zsh ได้ (ฉันพยายามnoglobไม่ประสบความสำเร็จ)

แก้ไข: แทนที่จะใช้sedหรือ!$:t(ซึ่งใช้งานไม่ได้ใน zsh สำหรับฉันแล้ว) ฉันพบสองตัวเลือกอื่น (หนึ่งการปรับhttps://unix.stackexchange.com/users/5685/frederik-deweerdtคำตอบด้วยhttps : //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

หาก repo url ของคุณสิ้นสุดลง.gitคุณสามารถใช้!$:t:rเพื่อรับชื่อโฟลเดอร์
Michael Stramel

2

วิธีแก้ไขปัญหาที่ง่ายสำหรับ POSIX เชลล์คือการระบุไดเร็กตอรี่ที่จะโคลนให้ชัดเจน (พา ธ ระบบไฟล์ใด ๆ ) และนำมาใช้ใหม่:

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; whateverหรือwhatever; git clone fooหรือgit clone --option repo...


+1 ขอบคุณมากสำหรับรหัส; ฉันใช้มันตั้งแต่ไม่กี่วัน ฉันเพิ่งสังเกตเห็นปัญหาหนึ่ง; ถ้าคุณปิดขั้วขวาหลังจากโคลนบางโครงการในครั้งต่อไปที่คุณเปิด terminal ที่ zsh บ่นกับข้อความผิดพลาดที่สอง: และCDing into <project> ข้อผิดพลาดที่หายไปทันทีที่คำสั่งสุดท้ายที่คุณวิ่งก่อนที่จะปิดสถานีที่แตกต่างจากclone_check:cd:17: no such file or directory: <project> $ git clone
user938271

2

นี่คือการปรับคำตอบข้างต้นสำหรับ OSX

  • mktemp ต้องใช้พารามิเตอร์เพิ่มเติม
  • git cloneเขียนถึงSTDERRโดยค่าเริ่มต้น (ดูนี้ )

ฟังก์ชั่น:

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

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ทำ

ไม่ว่าคุณจะสามารถใช้กระดาษห่อคอมไพล์และไม่ต้องกังวลเกี่ยวกับความสำเร็จของคุณหรือคุณสามารถกำจัดเสื้อคลุมคอมไพล์และ rewire ของคุณสำเร็จไปgit clonegit-clone

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.