2017-03-08 15 views
5

Birçok farklı Git dalı kullanarak büyük bir C++ projesi üzerinde çalışıyorum. Git Flow modelini kullanıyoruz. Bu düzenli olarak Git dalları arasında geçiş yaptığım anlamına gelir. Kodda gezinmek için Emacs'te helm-gtags kullanıyorum. Şu anda, Git sürüm kontrolü altında GNU Global etiket dosyalarını (GTAGS, GRTAGS, GPATH) yerleştirmediğim için, farklı bir dal üzerinde çalışmak üzere değiştiğimde, sadece bunlar kalıyor. Ancak bu, kodda bulunmayan etiket dosyalarında semboller olduğu anlamına gelebilir ve bunun tersi de olabilir. Etiket dosyalarını (helm-gtags-update-tags) güncelleyebilirim ancak bu kodda bulunmayan etiket dosyalarındaki sembolleri kaldırmaz, sadece kodda yer alan sembolleri ekler veya günceller.Farklı Git dallarındaki GNU Global etiket dosyalarının doğru kullanımı

GNU Global etiket dosyalarında Git tarafından kontrol edilen bir sürümde kodla çalışmak için en iyi yol nedir? Etiket dosyaları Git'e eklenmeli, böylece her bir branşa özel olacaklar mı? Ya da yeni bir etiket seti oluşturmak için şubeye her geçiş yaptığımda etiket dosyalarını silmem gerekir mi? Ya da başka bir yol var mı? Etiket dosyaları belirli bir kod sürümüyle ilişkili olduğundan

+0

Katılıyorum, devam et ve göç et. –

+0

Global -u'yi .git/hooks/post-checkout konumuna getirin. – politza

+0

@politza global -u', "kodda bulunmayan etiket dosyalarındaki sembolleri kaldırmaz, yalnızca kodda yer alan sembolleri ekler veya günceller" sorunuyla ilgilenir? Sadece 'dümen-gtags-update-tags' 'global -u' diye çağırabildiğini hayal edebiliyorum, bu yüzden yetersiz gibi görünüyor. Gerçi bu gerekli olan her şeye rağmen, ve tüm değişen dosyaları fark edecek kadar zeki, o zaman bunun en basit çözüm olduğunu kabul ediyorum. – phils

cevap

0

, ben

Öte yandan

, onlar koduyla çalışma belirli bir stil dosyaları. Eğer onları kontrol etmelisiniz inanıyoruz ve Bu nedenle, genel olarak projeye uygulanamaz ve bu nedenle kontrol edilmemesi gerektiği söylenebilir. Her bir işleme sürekli olarak değişecek ve çok fazla gürültü ekleyeceklerdir. Diğer herkesin bakmak zorunda olduğu gürültü.

Bunun yerine önerim, emacs'i yapılandırmayı incelemektir; böylece, dosyaları değiştirdiklerinde otomatik olarak otomatik olarak günceller. Bu çoğu modern editörün yaptığı şeydir. Here's a technique using inotify. Ya da bunun sapkın olduğunu biliyorum, yeni bir editör için zaman olabilir. Emacs'tan bu yıl Atom'a geçtim.

0

Onlara ulaştırmak en iyi fikir gibi görünmüyor ve tüm projenizi yeniden global hale getirmenin ne kadar sürdüğüne bağlı olarak, şubeleri her değiştirdiğinizde tüm veritabanını yeniden oluşturmak için istenmeyen bir durum olabilir.

Tam bir yeniden oluşturma işlemi çok uzun sürerse, işlenmemiş dosyaları şube başına temelinde yönetmek için yazdığım post-checkout git kanca.

Her bir dal için, GTAGS, GRTAGS, GPATH dosyalarınızı bu betik tarafından kullanılan .branches dizininin uygun adlı bir alt dizinine kopyalamanız gerekir ve daha sonra, betik dalları değiştirdiğinizde dosyaları değiştirir.

#!/bin/sh 

# Git hook (post-checkout) to manage *untracked* files on a per-branch basis. 
# Author: Phil S. 
# Version 1.1 
# URL: http://stackoverflow.com/a/42686433 

## Commentary: 
# 
# This hook is very useful when you have development-specific files which 
# you never want to commit to the repository, but which can vary on a 
# branch-by-branch basis. Branch-specific configuration files are a 
# prime use-case (to specify the database to use, for instance). 
# 
# With this hook, those files are automatically copied into the working 
# copy when you checkout the branch they are associated with, and moved 
# back again when you checkout another branch. 
# 
# The hook uses a .branches directory in the root of the repository, 
# so you should add this to your .gitignore file. 
# 
# To start managing files for a branch, simply copy them into a sub- 
# directory (of .branches) named after the branch in question, changing 
# any forward slashes in the branch name into double-underscores. 


## Example: 
# 
# [phil/master] ~/site$ grep .branches .gitignore 
# .branches 
# 
# [phil/master] ~/site$ find .branches/ 
# .branches/ 
# .branches/phil__master 
# .branches/phil__master/sites 
# .branches/phil__master/sites/default 
# .branches/phil__master/sites/default/settings.branch.php 
# .branches/phil__media 
# .branches/phil__media/sites 
# .branches/phil__media/sites/default 
# .branches/phil__media/sites/default/settings.branch.php 
# 
# [phil/master] ~/site$ git checkout phil/media 
# Switched to branch 'phil/media' 
# Removing untracked per-branch files for: phil__master 
# `../.././sites/default/settings.branch.php' -> `./sites/default/settings.branch.php' 
# Adding untracked per-branch files for: phil__media 
# >f+++++++++ sites/default/settings.branch.php 


## Caveat: 
# 
# An early version of this script had issues whenever a git operation checked 
# out a detached HEAD, such that the .branches/.current_branch file contained 
# "HEAD" rather than the branch directory name, and so the intended untracked 
# files were not copied. 
# 
# I never got caught out by this, because my prompt always shows me the 
# .current_branch value (see comments at the end of the hook), so I notice 
# when it says HEAD unexpectedly; however I do not recall this happening at 
# all in the past few years, so I believe it is no longer a concern. 
# 
# If it were to happen to you, simply running git checkout (branch) for the 
# branch you are already on fixes it up. The log file may also help to debug 
# any such issues. 
# 
# n.b. It's feasible that git could update the HEAD ref without performing 
# a checkout (after initially checking out a detached head), but the cases 
# I've observed (and fixed) were associated with rebasing, where this script 
# had (undesirably) permitted its own processing to occur after an initial 
# checkout of a detached HEAD, and had then exited early (as intended when 
# rebasing) after the subsequent checkout of the eventual branch. The solution 
# was to improve the detection of the cases in which we wish to exit early, 
# to cover the former case as well as the latter. 


## Changelog: 
# 
# v1.1: Handle additional text following "rebase" in GIT_REFLOG_ACTION. 
#  Renamed $git_dir to $root (it's the working copy root, not .git) 
#  Log git environment vars even when aborting. 


## General information on Git post-checkout hooks: 
# 
# This hook is invoked when a git checkout is run after having updated 
# the worktree. The hook is given three parameters: the ref of the 
# previous HEAD, the ref of the new HEAD (which may or may not have 
# changed), and a flag indicating whether the checkout was a branch 
# checkout (changing branches, flag=1) or a file checkout (retrieving 
# a file from the index, flag=0). This hook cannot affect the outcome 
# of git checkout. 
# 
# It is also run after git clone, unless the --no-checkout (-n) option 
# is used. The first parameter given to the hook is the null-ref, the 
# second the ref of the new HEAD and the flag is always 1. 
# 
# This hook can be used to perform repository validity checks, 
# auto-display differences from the previous HEAD if different, or set 
# working dir metadata properties. 

############################################################################## 

head_old=$1 
head_new=$2 
flag=$3 

# n.b. pwd will be this working copy's root directory. 
root=$(pwd) 

# Debug log. 
log=".branches/post-checkout.log" 
echo "\n$(date)" >>${log} 2>&1 
if test -f .branches/.current_branch; then 
    echo ".current_branch: $(cat .branches/.current_branch)" >>${log} 2>&1 
else 
    echo ".current_branch (file missing)" >>${log} 2>&1 
fi 
echo "Old: $(git log --max-count=1 --decorate ${head_old} | head -1)" >>${log} 2>&1 
echo "New: $(git log --max-count=1 --decorate ${head_new} | head -1)" >>${log} 2>&1 

# Log the GIT environment variables. This is primarily to assist with finding 
# workarounds for any edge cases that might crop up. (This is how I discovered 
# GIT_REFLOG_ACTION.) 
set | grep GIT >>${log} 2>&1 

# Check the 'flag' parameter ($3). 
if test "$flag" != "1"; then # not a branch switch. 
    echo "$0 aborted (not a branch switch)." 2>&1 | tee -a ${log} 
    echo "Check ${log} for details." 
    exit 0 
fi 

# This hook is also invoked with flag=1 when rebasing, which we never want. 
# We only want to move the untracked files around when we have explictly 
# requested a checkout (which also means that the .current_branch file must 
# only ever be updated at those same times). 
if test "${GIT_REFLOG_ACTION##rebase}" != "${GIT_REFLOG_ACTION}"; then 
    echo "$0 aborted (GIT_REFLOG_ACTION indicated rebase)." 2>&1 | tee -a ${log} 
    echo "Check ${log} for details." 
    exit 0 
elif test -d "$root/.git/rebase-merge"; then 
    echo "$0 aborted (.git/rebase-merge indicated rebase)." 2>&1 | tee -a ${log} 
    echo "Check ${log} for details." 
    exit 0 
fi 

# Determine which .branches directory we were originally using. 
# There is no pre-checkout hook, but we can include a marker file amongst 
# the untracked files identifying the current branch name, and use that to 
# update the versions of the files under .branches from the current versions 
# before copying the new versions. 
cd "$root" 
if test -f .branches/.current_branch; then 
    oldbranch=$(cat .branches/.current_branch) 
    oldbranch_dir=".branches/$oldbranch" 
    if test -d "$oldbranch_dir"; then 
     echo "Removing untracked per-branch files for: $oldbranch" 
     cd "$oldbranch_dir" 
     find . -type f -print0 | xargs -0r -I{} mv -v -f ../../{} {} 
    fi 
fi 

# Establish the name of the newly checked-out branch. 
cd "$root" 
newbranch=$(git symbolic-ref -q HEAD) 
newbranch=${newbranch##refs/heads/} 
newbranch=${newbranch:-HEAD} 
newbranch=$(echo $newbranch | sed 's/\//__/') 
newbranch_dir=".branches/$newbranch" 

# Create/update marker file. 
test -d .branches || mkdir .branches 
echo $newbranch >.branches/.current_branch 
echo ".current_branch: $(cat .branches/.current_branch)" >>${log} 2>&1 

# Copy across the untracked files needed for the new branch. 
echo "Adding untracked per-branch files for: $newbranch" 

if ! test -d "$newbranch_dir"; then 
    echo "$newbranch_dir not found; nothing to update." 
    exit 0 
fi 

cd "$newbranch_dir" 
rsync -r -i . ../../ 

# You can also set a fancy prompt in bash to show you which branch you're in. 
# (Used to be super-useful when rebasing was a problem, but probably still 
# handy just for confirming that things are as they should be.) 
# PS1="${debian_chroot:+($debian_chroot)}\[email protected] [\$(cat /var/www/(site)/.branches/.current_branch | sed 's/__/\//')] \w\$ " 

# Local Variables: 
# outline-regexp: "^##" 
# eval: (outline-minor-mode 1) 
# eval: (while (re-search-forward "^## .+:" nil t) (outline-toggle-children)) 
# End: 

Şahsen Global Ctags dan geçiş yaptı gitmedim ve benim Etiketler tutmanın genel sorununa oldukça kaba kuvvet yaklaşım kullanmak çalıştırmak için bir zamanlayıcı kullanmaktır güncel, dosya herhangi bir dosyanın TAGS'den daha yeni bir tarihte değiştirilip değiştirilmediğini ve varsa, yeni bir TAGS dosyası oluşturup oluşturmadığını belirlemek için eşzamansız bir kabuk komutu. Yeni dosya eski dosyaya göre farklıysa, eski olanı değiştiririm ve Emacs etiketleri tamamlama tablosunu sıfırlayacak ve böylece bir dahaki sefere TAGS dosyasını yeniden okuyacaktır.

Bu nedenle TAGS dosyasını yeniden oluşturmak, hem geçerli dalda hem de başka bir şubeye geçmek için kod değişikliklerini yapmak için benim çözümümdür. Bu nedenle, ödeme-sonrası kancalarımı amaç için kullanmam için çok fazla nedenim olmadı Burada önerdim. Zamanlayıcı tetiklendiğinde, kod değişiklikleri ile yakalanan TAGS dosyası arasında birkaç dakika gecikme olabilir, bu yüzden daha hızlı bir yanıt daha güzel olur.

0

Sonunda yaptığım şey budur. Etiket dosyalarını git'e eklemeye başladım. Ancak bu, dallanma ve birleştirme ile iyi çalışmadığını kanıtladı ve sonunda etiket dosyaları mevcut daldaki tüm sembolleri içermeyecek ve daha fazla bir şey olmayacaktı. Phils cevap git kancaları kontrol etmemi sağladı.Etiket dosyalarını git sürümlerinden kaldırdım ve dalları değiştirirken mevcut olan tüm etiket dosyalarını sessizce silen bir posta çıkış kancası oluşturdum. Emacs'teki helm-gtags, bunları oluşturmak için sunduğu herhangi bir etiket dosyası olmadığını tespit ettiğinde. Oldukça büyük olan projem için uzun sürmez. helm-gtags ayrıca bir dosyanın ne zaman değiştiğini algılar ve etiket dosyalarını yalnızca bu değişikliklerle otomatik olarak günceller. Şimdi şimdi mevcut şubedeki tüm sembollerle etiket dosyalarını güncel tutan bir sistemim var. Şimdiye kadar iyi çalışıyor.