Mercurial มีวิธีการพิมพ์ไดเรกทอรีรูท (ที่มี. hg) ผ่านทาง
hg root
มีบางสิ่งที่เทียบเท่าใน git เพื่อรับไดเรกทอรีที่มีไดเรกทอรี. git หรือไม่
bzr rootถูกนำมาใช้อย่างมากใน Bazaar
git rev-parse --git-dirตามที่อธิบายในความคิดเห็นนี้
Mercurial มีวิธีการพิมพ์ไดเรกทอรีรูท (ที่มี. hg) ผ่านทาง
hg root
มีบางสิ่งที่เทียบเท่าใน git เพื่อรับไดเรกทอรีที่มีไดเรกทอรี. git หรือไม่
bzr rootถูกนำมาใช้อย่างมากใน Bazaar
git rev-parse --git-dirตามที่อธิบายในความคิดเห็นนี้
คำตอบ:
ใช่:
git rev-parse --show-toplevel
หากคุณต้องการทำซ้ำคำสั่ง Git โดยตรงคุณสามารถสร้างนามแฝงได้ :
git config --global alias.root 'rev-parse --show-toplevel'
และตอนนี้จะทำงานเช่นเดียวกับที่git roothg root
หมายเหตุ : ใน submodule สิ่งนี้จะแสดงไดเร็กทอรีรูทของsubmoduleและไม่ใช่ที่เก็บพาเรนต์ หากคุณใช้ Git> = 2.13 ขึ้นไปมีวิธีที่submodules สามารถแสดงไดเรกทอรีรากของ superproject หากคอมไพล์ของคุณเก่ากว่านี้ให้ดูคำตอบอื่น ๆ
git config --global alias.exec '!exec ' git exec makeใช้งานได้เนื่องจากเชลล์นามแฝงนั้นจะถูกเรียกใช้งานในไดเรกทอรีระดับบนสุดเสมอ
hg rootไม่ มันจะพิมพ์ไดเรกทอรีระดับบนสุดของที่เก็บที่คุณเช็คเอาต์ มันไม่ได้เปลี่ยนคุณไปเป็นมัน (และอันที่จริงแล้วมันทำไม่ได้เพราะวิธีการที่แนวคิดทั้งหมดของไดเรกทอรีปัจจุบันและเชลล์ของคุณมีปฏิสัมพันธ์)
~/my.proj/foo/barและ~/my.projเป็น symlinked ไปที่คำสั่งดังกล่าวจะย้ายคุณไป~/src/my.proj ~/src/my.projอาจเป็นปัญหาหากสิ่งที่คุณต้องการทำหลังจากนั้นไม่ใช่ผู้ไม่เชื่อเรื่องพระเจ้า
.gitไดเรกทอรีของโครงการ
manหน้าgit-config(ภายใต้นามแฝง ) พูดว่า:
หากส่วนขยาย alias ถูกเติมหน้าด้วยเครื่องหมายอัศเจรีย์จะถูกใช้เป็นคำสั่งเชลล์ [... ] โปรดทราบว่าคำสั่งเชลล์จะถูกดำเนินการจากไดเรกทอรีระดับบนสุดของที่เก็บซึ่งอาจไม่จำเป็นต้องเป็นไดเรกทอรีปัจจุบัน
ดังนั้นใน UNIX คุณสามารถทำได้:
git config --global --add alias.root '!pwd'
.zshrcและฉันกำหนด `alias cg =" cd $ (git root) "ส่วน $ () จะได้รับการประเมิน ณ แหล่งเวลาและชี้ไปที่ ~ / dotfiles เสมอเพราะเป็นที่ที่ zshrc ของฉันอยู่ .
ได้--show-toplevelเพียงไม่นานมารับการเพิ่มgit rev-parseหรือทำไมไม่มีใครเอ่ยถึงมันได้หรือไม่
จากgit rev-parseหน้าคน:
--show-toplevel
Show the absolute path of the top-level directory.
git-rev-parseเพราะชื่อของมันบอกว่ามันเกี่ยวกับการประมวลผลข้อกำหนดการแก้ไข BTW ฉันยินดีที่จะเห็นgit --work-treeงานที่คล้ายกับgit --exec-path[=<path>]: "หากไม่มีเส้นทางที่ได้รับ git จะพิมพ์การตั้งค่าปัจจุบัน"; อย่างน้อย IMO ก็เป็นสถานที่ที่เหมาะสมสำหรับการค้นหาคุณลักษณะดังกล่าว
root = rev-parse --show-toplevelใน gitconfig ของคุณ
git config --global alias.root "rev-parse --show-toplevel"และจากนั้นgit rootจะสามารถทำงาน
git rev-parse --show-toplevelทำงานเมื่อฉันพยายามใน submodule มันพิมพ์ dir รากของ submodule คอมไพล์ มันพิมพ์อะไรให้คุณ
--show-cdupถึง--show-top-levelในกุมภาพันธ์ 2011 (หลังจากส่งคำตอบนี้)
แล้ว " git rev-parse --git-dir" ล่ะ
F:\prog\git\test\copyMerge\dirWithConflicts>git rev-parse --git-dir
F:/prog/git/test/copyMerge/.git
--git-dirตัวเลือกที่ดูเหมือนว่าจะทำงาน
--git-dir
Show $GIT_DIR if defined else show the path to the .git directory.
คุณสามารถดูได้ในสคริปต์นี้git setup-shนี้
หากคุณอยู่ในโฟลเดอร์ submodule ด้วย Git> = 2.13ให้ใช้ :
git rev-parse --show-superproject-working-tree
หากคุณกำลังใช้git rev-parse --show-toplevel, ให้แน่ใจว่ามันอยู่กับ Git 2.25+ (ไตรมาสที่ 1 ปี 2020)
.gitหากคุณอยู่ในไดเรกทอรีรากแล้ว (อย่างน้อยก็ทำใน msysgit)
เขียนคำตอบง่ายๆที่นี่เพื่อเราจะได้ใช้
git root
ในการทำงานเพียงกำหนดค่า git ของคุณโดยใช้
git config --global alias.root "rev-parse --show-toplevel"
และจากนั้นคุณอาจต้องการเพิ่มสิ่งต่อไปนี้ใน~/.bashrc:
alias cdroot='cd $(git root)'
เพื่อให้คุณสามารถใช้cdrootเพื่อไปด้านบนสุดของ repo ของคุณ
หากคุณอยู่ในระดับบนสุดแล้วหรือไม่อยู่ในพื้นที่เก็บข้อมูล git cd $(git rev-parse --show-cdup)คุณจะได้กลับบ้าน (แค่ cd) cd ./$(git rev-parse --show-cdup)เป็นวิธีหนึ่งในการแก้ไขที่
cd "$(git rev-parse --show-cdup)"อีกตัวเลือกหนึ่งคือการพูดมัน งานนี้เพราะจะนำคุณไม่มีที่ไหนเลยแทนที่จะกลับcd "" $HOMEและเป็นแนวปฏิบัติที่ดีที่สุดในการเสนอราคาการร้องขอ $ () ต่อไปในกรณีที่พวกเขาแสดงผลลัพธ์ด้วยช่องว่าง (ไม่ใช่ว่าคำสั่งนี้จะเกิดขึ้นในกรณีนี้)
$PWDขณะที่พวกเขาไม่สามารถแก้ไดเรกทอรีรากคอมไพล์ของเทียบกับทุบตี ตัวอย่างนี้จะแก้ปัญหารากคอมไพล์ญาติไปแทน$PWD realpath $PWD
ในการคำนวณพา ธ สัมบูรณ์ของไดเรกทอรีราก git ปัจจุบันพูดเพื่อใช้ในเชลล์สคริปต์ใช้ชุดของ readlink และ git rev-parse นี้:
gitroot=$(readlink -f ./$(git rev-parse --show-cdup))
git-rev-parse --show-cdupให้จำนวนที่ถูกต้องของ ".. " เพื่อไปยังรูทจาก cwd ของคุณหรือสตริงว่างถ้าคุณอยู่ที่รูท จากนั้นเติม "./" เพื่อจัดการกับสตริงตัวพิมพ์ว่างและใช้
readlink -fเพื่อแปลเป็นพา ธ แบบเต็ม
คุณสามารถสร้างgit-rootคำสั่งใน PATH ของคุณเป็นเชลล์สคริปต์เพื่อใช้เทคนิคนี้:
cat > ~/bin/git-root << EOF
#!/bin/sh -e
cdup=$(git rev-parse --show-cdup)
exec readlink -f ./$cdup
EOF
chmod 755 ~/bin/git-root
(ด้านบนสามารถวางลงในเทอร์มินัลเพื่อสร้าง git-root และตั้งค่าบิตรันสคริปต์จริงอยู่ในบรรทัดที่ 2, 3 และ 4)
และจากนั้นคุณจะสามารถเรียกใช้git rootเพื่อรับรูทของทรีปัจจุบันของคุณ โปรดทราบว่าในเชลล์สคริปต์ให้ใช้ "-e" เพื่อทำให้เชลล์ออกหากการแยกวิเคราะห์ซ้ำล้มเหลวเพื่อให้คุณสามารถรับสถานะการออกและข้อความแสดงข้อผิดพลาดได้อย่างถูกต้องหากคุณไม่ได้อยู่ในไดเรกทอรี git
"$(git rev-parse ...)" ./$(git rev-parse ...)
git rev-parse --show-cdupเป็นคนอื่นได้ตั้งข้อสังเกตหลักของการแก้ปัญหาคือการใช้งาน อย่างไรก็ตามมีที่อยู่บางกรณีที่จะอยู่:
เมื่อ cwd เป็นรากของแผนผังการทำงานแล้วคำสั่งจะให้สตริงว่าง
ที่จริงแล้วมันสร้างบรรทัดว่าง แต่การทดแทนคำสั่งถอดแถบตัวแบ่งบรรทัดต่อท้าย ผลลัพธ์สุดท้ายคือสตริงว่าง
คำตอบส่วนใหญ่แนะนำให้ prepending ส่งออกที่มี./เพื่อให้การส่งออกที่ว่างเปล่ากลายเป็นก่อนที่จะเลี้ยง"./"cd
เมื่อ GIT_WORK_TREE ถูกตั้งค่าเป็นตำแหน่งที่ไม่ใช่พาเรนต์ของ cwd เอาต์พุตอาจเป็นชื่อพา ธ สัมบูรณ์
การเตรียม./เป็นสิ่งที่ผิดในสถานการณ์นี้ ถ้า a ./ถูกผนวกเข้ากับพา ธ สัมบูรณ์มันจะกลายเป็นพา ธ สัมพัทธ์ (และจะอ้างถึงตำแหน่งเดียวกันหาก cwd เป็นไดเรกทอรีรูทของระบบ)
ผลลัพธ์อาจมีช่องว่าง
กรณีนี้ใช้เฉพาะในกรณีที่สอง แต่มีการแก้ไขที่ง่าย: ใช้เครื่องหมายคำพูดคู่รอบการทดแทนคำสั่ง (และการใช้ค่าในภายหลัง)
ดังที่คำตอบอื่น ๆ ได้บันทึกไว้เราสามารถทำได้cd "./$(git rev-parse --show-cdup)"แต่การแบ่งในกรณีขอบที่สอง (และกรณีขอบที่สามหากเราไม่ใส่เครื่องหมายคำพูดคู่)
เชลล์จำนวนมากถือว่าcd ""เป็น no-op ดังนั้นสำหรับเชลล์เหล่านั้นที่เราสามารถทำได้cd "$(git rev-parse --show-cdup)"(เครื่องหมายอัญประกาศคู่ปกป้องสตริงว่างเป็นอาร์กิวเมนต์ในเคส edge แรกและเก็บ whitespace ในเคส edge ที่สาม) POSIX บอกว่าผลลัพธ์ของcd ""ไม่ได้ระบุไว้ดังนั้นจึงเป็นการดีที่สุดที่จะหลีกเลี่ยงการตั้งสมมติฐานนี้
วิธีการแก้ปัญหาที่ใช้งานได้ในทุกกรณีข้างต้นต้องใช้การทดสอบบางอย่าง เสร็จสิ้นอย่างชัดเจนอาจมีลักษณะเช่นนี้:
cdup="$(git rev-parse --show-cdup)" && test -n "$cdup" && cd "$cdup"
ไม่cdทำสำหรับเคสตัวแรก
หากเป็นที่ยอมรับให้รันcd .สำหรับเคสขอบแรกดังนั้นเงื่อนไขสามารถทำได้ในการขยายพารามิเตอร์:
cdup="$(git rev-parse --show-cdup)" && cd "${cdup:-.}"
git root' ซึ่งเป็นคำตอบที่คุณใช้?
ในกรณีที่คุณกำลังป้อนเส้นทางนี้ไปยัง Git เองให้ใช้ :/
# this adds the whole working tree from any directory in the repo
git add :/
# and is equal to
git add $(git rev-parse --show-toplevel)
คำตอบสั้น ๆ ที่ใช้งานได้กับ submodules, hooks, และภายใน .gitไดเรกทอรี
นี่คือคำตอบสั้น ๆ ที่คนส่วนใหญ่ต้องการ:
r=$(git rev-parse --git-dir) && r=$(cd "$r" && pwd)/ && echo "${r%%/.git/*}"
สิ่งนี้จะทำงานที่ใดก็ได้ในแผนผังการทำงาน git (รวมถึงภายใน.gitไดเรกทอรี) แต่สมมติว่ามีการเรียกไดเรกทอรีเก็บข้อมูล.git(ซึ่งเป็นค่าเริ่มต้น) ด้วย submodules สิ่งนี้จะไปที่รูทของพื้นที่เก็บข้อมูลด้านนอกสุด
หากคุณต้องการไปที่รูทของการใช้ submodule ปัจจุบัน:
echo $(r=$(git rev-parse --show-toplevel) && ([[ -n $r ]] && echo "$r" || (cd $(git rev-parse --git-dir)/.. && pwd) ))
ในการดำเนินการคำสั่งในรูท submodule ของคุณอย่างง่ายดายภายใต้[alias]ของคุณ.gitconfigให้เพิ่ม
sh = "!f() { root=$(pwd)/ && cd ${root%%/.git/*} && git rev-parse && exec \"$@\"; }; f"
สิ่งนี้ช่วยให้คุณทำสิ่งต่าง ๆ เช่น git sh ag <string>
โซลูชันที่แข็งแกร่งซึ่งรองรับชื่อแตกต่างกันหรือภายนอก.gitหรือ$GIT_DIRไดเรกทอรี
โปรดทราบว่า$GIT_DIRอาจชี้ที่ภายนอก (และไม่ถูกเรียก.git ) ดังนั้นจึงจำเป็นต้องมีการตรวจสอบเพิ่มเติม
ใส่สิ่งนี้ใน.bashrc:
# Print the name of the git working tree's root directory
function git_root() {
local root first_commit
# git displays its own error if not in a repository
root=$(git rev-parse --show-toplevel) || return
if [[ -n $root ]]; then
echo $root
return
elif [[ $(git rev-parse --is-inside-git-dir) = true ]]; then
# We're inside the .git directory
# Store the commit id of the first commit to compare later
# It's possible that $GIT_DIR points somewhere not inside the repo
first_commit=$(git rev-list --parents HEAD | tail -1) ||
echo "$0: Can't get initial commit" 2>&1 && false && return
root=$(git rev-parse --git-dir)/.. &&
# subshell so we don't change the user's working directory
( cd "$root" &&
if [[ $(git rev-list --parents HEAD | tail -1) = $first_commit ]]; then
pwd
else
echo "$FUNCNAME: git directory is not inside its repository" 2>&1
false
fi
)
else
echo "$FUNCNAME: Can't determine repository root" 2>&1
false
fi
}
# Change working directory to git repository root
function cd_git_root() {
local root
root=$(git_root) || return 1 # git_root will print any errors
cd "$root"
}
ดำเนินการได้โดยการพิมพ์git_root(หลังจากรีสตาร์ทเปลือกของคุณ: exec bash)
(root=$(git rev-parse --git-dir)/ && cd ${root%%/.git/*} && git rev-parse && pwd)แต่สิ่งนี้ไม่ครอบคลุม$GIT_DIRs ภายนอกที่มีชื่ออื่นที่ไม่ใช่.git
หากต้องการแก้ไข "git config" ให้ตอบเพียงเล็กน้อย:
git config --global --add alias.root '!pwd -P'
และทำความสะอาดเส้นทาง ดีมาก.
หากคุณกำลังมองหานามแฝงที่ดีในการทำเช่นนี้และไม่ระเบิดcdถ้าคุณไม่ได้อยู่ในคอมไพล์ git:
alias ..g='git rev-parse && cd "$(git rev-parse --show-cdup)"'
git-extrasเพิ่ม$ git root
โปรดดูhttps://github.com/tj/git-extras/blob/master/Commands.md#git-root
$ pwd
.../very-deep-from-root-directory
$ cd `git root`
$ git add . && git commit
$ brew install git-extras$ apt-get install git-extrasนามแฝงของเชลล์นี้ทำงานได้ไม่ว่าคุณจะอยู่ในส่วนย่อย git หรือที่ระดับบนสุด:
alias gr='[ ! -z `git rev-parse --show-toplevel` ] && cd `git rev-parse --show-toplevel || pwd`'
อัปเดตเพื่อใช้ไวยากรณ์ที่ทันสมัยแทน backticks:
alias gr='[ ! -z $(git rev-parse --show-toplevel) ] && cd $(git rev-parse --show-toplevel || pwd)'
alias git-root='cd \`git rev-parse --git-dir\`; cd ..'
ทุกอย่างอื่นล้มเหลวในบางจุดไม่ว่าจะไปที่ไดเรกทอรีบ้านหรือเพียงแค่ความล้มเหลวอย่างน่าสังเวช นี่เป็นวิธีที่เร็วและสั้นที่สุดในการกลับไปที่ GIT_DIR
$GIT_DIRถูกถอดออกจาก workingtree โดยใช้.git-Files gitdir: SOMEPATHและ ดังนั้นนี้ล้มเหลวสำหรับ submodules เกินไปที่มี$GIT_DIR .git/modules/SUBMODULEPATH
นี่คือสคริปต์ที่ฉันเขียนที่จัดการทั้งสองกรณี: 1) ที่เก็บพร้อมเวิร์กสเปซ 2) ที่เก็บเปลือย
https://gist.github.com/jdsumsion/6282953
git-root (ไฟล์ปฏิบัติการในเส้นทางของคุณ):
#!/bin/bash
GIT_DIR=`git rev-parse --git-dir` &&
(
if [ `basename $GIT_DIR` = ".git" ]; then
# handle normal git repos (with a .git dir)
cd $GIT_DIR/..
else
# handle bare git repos (the repo IS a xxx.git dir)
cd $GIT_DIR
fi
pwd
)
หวังว่านี่จะเป็นประโยชน์
git execว่าความคิดที่เป็นประโยชน์มากขึ้นในที่เก็บที่ไม่ได้เปลือย อย่างไรก็ตามสคริปต์นี้ในคำตอบของฉันจัดการกับกรณีที่ไม่ได้รับการเปลือยและไม่ถูกต้องซึ่งอาจเป็นประโยชน์กับใครบางคนดังนั้นฉันจึงทิ้งคำตอบไว้ที่นี่
git submodules ที่มีสิ่งที่ต้องการ$GIT_DIR /.git/modules/SUBMODULEนอกจากนี้คุณสมมติว่า.gitไดเรกทอรีเป็นส่วนหนึ่งของ worktree ในกรณีที่ไม่ใช่แบบเปลือย
$ git config alias.root '!pwd'
# then you have:
$ git root
[alias] findroot = "!f () { [[ -d ".git" ]] && echo "Found git in [pwd ]" && exit 0; cd .. && echo "IN pwd" && f;}; f"
git config --global alias.root '!pwd'ทำงาน ฉันไม่สามารถมองเห็นกรณีใด ๆ ที่มันทำหน้าที่แตกต่างจากตัวแปรที่ไม่ใช่สากล (Unix, git 1.7.10.4) BTW: คุณfindrootต้องการ a /.gitเพื่อหลีกเลี่ยงการเรียกซ้ำที่ไม่สิ้นสุด
ตั้งแต่Git 2.13.0มันสนับสนุนตัวเลือกใหม่เพื่อแสดงเส้นทางของโครงการรากซึ่งทำงานได้แม้จะถูกใช้จากภายใน submodule:
git rev-parse --show-superproject-working-tree
หากคุณใช้เชลล์เฟรมเวิร์กอาจมีสมนามเชลล์อยู่แล้ว:
$ grtในoh-my-zsh (68k) ( cd $(git rev-parse --show-toplevel || echo "."))$ git-rootในprezto (8.8k) (แสดงเส้นทางไปยังรากของต้นไม้ที่ทำงาน)$ g.. zimfw (1k) (เปลี่ยนไดเรกทอรีปัจจุบันเป็นระดับบนสุดของแผนผังการทำงาน)ฉันต้องการขยายความคิดเห็นที่ยอดเยี่ยมของ Daniel Brockman
การกำหนดgit config --global alias.exec '!exec 'อนุญาตให้คุณทำสิ่งต่าง ๆ เช่นgit exec makeในฐานะman git-configรัฐ:
หากส่วนขยาย alias ถูกเติมหน้าด้วยเครื่องหมายอัศเจรีย์จะถูกใช้เป็นคำสั่งเชลล์ [... ] โปรดทราบว่าคำสั่งเชลล์จะถูกดำเนินการจากไดเรกทอรีระดับบนสุดของที่เก็บซึ่งอาจไม่จำเป็นต้องเป็นไดเรกทอรีปัจจุบัน
นอกจากนี้ยังมีประโยชน์ที่จะรู้ว่า$GIT_PREFIXจะเป็นเส้นทางไปยังไดเรกทอรีปัจจุบันเทียบกับไดเรกทอรีระดับบนสุดของที่เก็บ แต่รู้ว่ามันเป็นเพียงครึ่งหนึ่งของการต่อสู้™ การขยายตัวแปรเชลล์ทำให้ใช้งานค่อนข้างยาก ดังนั้นฉันแนะนำให้ใช้bash -cดังนี้:
git exec bash -c 'ls -l $GIT_PREFIX'
คำสั่งอื่น ๆ ได้แก่ :
git exec pwd
git exec make
ในกรณีที่ทุกคนต้องการวิธีที่เป็นไปตาม POSIX ในการทำเช่นนี้โดยไม่จำเป็นต้องgitปฏิบัติการได้:
#$1: Path to child directory
git_root_recurse_parent() {
# Check if cwd is a git root directory
if [ -d .git/objects -a -d .git/refs -a -f .git/HEAD ] ; then
pwd
return 0
fi
# Check if recursion should end (typically if cwd is /)
if [ "${1}" = "$(pwd)" ] ; then
return 1
fi
# Check parent directory in the same way
local cwd=$(pwd)
cd ..
git_root_recurse_parent "${cwd}"
}
git_root_recurse_parent
หากคุณเพียงต้องการให้การทำงานเป็นส่วนหนึ่งของสคริปต์ให้ลบ shebang และแทนที่git_root_recurse_parentบรรทัดสุดท้ายด้วย:
git_root() {
(git_root_recurse_parent)
}
ifคำสั่งที่สองควรจะตรวจสอบว่าคุณได้เปลี่ยนไดเรกทอรีในการสอบถามซ้ำ หากยังคงอยู่ในไดเรกทอรีเดียวกันมันจะถือว่าคุณติดอยู่ที่ใดที่หนึ่ง (เช่น/) และเบรกซ้ำ ข้อผิดพลาดได้รับการแก้ไขและควรทำงานได้ตามที่คาดไว้ ขอบคุณที่ชี้นำ
ต้องแก้ปัญหานี้ด้วยตัวเองวันนี้ แก้ไขใน C # ตามที่ฉันต้องการสำหรับโปรแกรม แต่ฉันคิดว่ามันสามารถเขียนใหม่ได้อย่างง่ายดาย พิจารณาโดเมนสาธารณะนี้
public static string GetGitRoot (string file_path) {
file_path = System.IO.Path.GetDirectoryName (file_path);
while (file_path != null) {
if (Directory.Exists (System.IO.Path.Combine (file_path, ".git")))
return file_path;
file_path = Directory.GetParent (file_path).FullName;
}
return null;
}