- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我正在使用许多不同的 Git 分支开发一个大型 C++ 项目。我们正在使用 Git Flow 模型。这意味着我会定期在 Git 分支之间切换。我在 Emacs 中使用 helm-gtags 来导航代码。目前我还没有将 GNU 全局标记文件(GTAGS、GRTAGS、GPATH)置于 Git 版本控制之下,只要我更改为在不同的分支上工作,它们就会保持不变。但这可能意味着我在标记文件中有代码中不存在的符号,反之亦然。我可以更新标签文件 (helm-gtags-update-tags),但这不会从标签文件中删除代码中不存在的符号,它只会添加或更新代码中实际存在的符号。
在由 Git 控制版本的代码中使用 GNU Global 标签文件的最佳方式是什么?是否应该将标记文件添加到 Git,以便它们特定于每个分支?或者我是否应该在每次切换分支以生成一组新标签时删除标签文件?还是有别的办法?
最佳答案
提交它们似乎不是最好的主意,并且根据 global 重新索引整个项目需要多长时间,您可能会发现每次更改分支时都重建整个数据库是不可取的。
如果完全重建花费的时间太长,这里是我编写的 post-checkout
git hook,用于在每个分支的基础上管理未跟踪的文件。
对于每个分支,您只需将 GTAGS、GRTAGS、GPATH 文件复制到此脚本使用的 .branches
目录的适当命名的子目录中,然后脚本将交换文件每当您更改分支机构时。
#!/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)}\u@ [\$(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:
就我个人而言,我从来没有从 Ctags 切换到 Global,我使用一种相当蛮力的方法来解决使我的 TAGS 文件保持最新的一般问题,即使用计时器来运行异步 shell 命令确定是否有任何文件比 TAGS 最近被修改,如果是,则构建一个新的 TAGS 文件。如果新文件与旧文件不同,我会替换旧文件并将 Emacs 的标签完成表设置为 nil,以便下次重新读取 TAGS 文件。
因此,重建 TAGS 文件是我在当前分支中进行代码更改以及切换到另一个分支的解决方案,因此我从来没有太多理由使用我的 post-checkout Hook 来达到我的目的在这里建议。不过,根据计时器触发的时间,代码更改和 TAGS 文件同步之间可能会有几分钟的延迟,因此更直接的响应会更好。
关于git - 在不同的 Git 分支中正确使用 GNU Global 标签文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42680131/
我时不时地输入“git”,然后想到别的东西,然后输入例如“git checkout master”。当然,这给我留下了 $ git git checkout master git: 'git' is
我做到了 git 克隆 git://foo.git 光盘富 ...编辑文件.. 现在我想重新开始。我不在乎我已经做出的任何改变,但我不想再次克隆整个巨型 foo.git,只是丢失我所有的更改。我怎
我在我的电脑上开发代码,我的计算节点很少。 为了让我的程序保持同步,我决定使用 git。以前,我以一种单向模式使用它来“下推”从 PC 到计算节点的更改。但是时不时遇到计算节点特有的小bug,现场修复
虽然它似乎什么也没做,但它没有给出任何警告或错误消息。有什么想法吗? 最佳答案 来自 Git 源的注释: /* * Read a directory tree. We currently ignor
我知道如何为这样的 HTTPS 请求提供用户名和密码: git clone https://username:password@remote 但我想知道如何像这样向 Remote 提供用户名和密码:
Git GUI、Git Bash 和 Git CMD 之间有什么区别?我是初学者,为了进行安装,我发现自己通常同时使用 git bash 和 git CMD 最佳答案 Git CMD 就像使用 git
有人能告诉我git中文件索引被删除是什么意思吗?这些文件在我的 VS Code 中标记为红色,但我仍然可以修改文件并将更改推送到将反射(reflect)这些更改的远程存储库。我认为这一切都是在我使用命
我通过 git 子树将 GLFV 库添加到项目中,但出现此警告“看起来您的 git 安装或您的 git-subtree 安装已损坏”。还描述了几个原因,为什么这可能是: 如 git --exec-pa
我有需要外部 git 项目的 repo,但我不想使用子模块,因为我想在 github 上存档所有文件,所以我认为我只是将具有 git repo 的整个目录添加到 git 但它不t 添加里面的 .git
我有需要外部 git 项目的 repo,但我不想使用子模块,因为我想在 github 上存档所有文件,所以我认为我只是将具有 git repo 的整个目录添加到 git 但它不t 添加里面的 .git
我一直在阅读一篇文章,作者在其中指示:在现有存储库中创建一个新存储库,并想知道这是否是他忽略的错误。稍后我会与他核实。 这些是我要检查的条件: 将现有目录制作成仓库的条件,并且已经 checkin 主
我确实在不同的计算机上处理相同的项目,我想知道是否有一种方法可以跟踪该 .git 文件夹,这样我就不必在所有本地文件中重新配置配置文件。 我将所有工作推送到 bitbucket。 最佳答案 不,没
这个问题在这里已经有了答案: How does git store files? (3 个答案) 关闭 9 年前。 我为我的许多项目创建了一个远程存储库,所以它是我的push 的目的地。与 git
应该如何在 git 中查看文件内容的完整历史记录? 一个文件在 git 中的历史很短,存储库通过 git-svn 同步,但在 svn 中的历史很长。 git 中的历史记录到达文件移动的位置。要查看历史
我是confused here ... 如何对修改后的文件进行git commit,以及如何对新文件进行git commit? 还有,你如何在git中单独提交文件? 最佳答案 git 提交过程分为两个
正在搜索 throw SO 来寻找答案。遇到这个似乎没有给出任何答案的旧线程。重新触发此线程,希望有人知道! 有人能告诉我 git subtree 和 git filter-branch 的区别吗?为
我想知道是否有一种方法可以避免在每个 Git 命令的开头键入单词 git。 如果有一种方法可以在打开命令提示符进入 “Git 模式” 后只使用一次 git 命令就好了。 例如: git> 之后,我们键
当您修改工作目录中的文件时,git 会告诉您使用“git add”暂存。 当您向工作目录添加新文件时,git 会告诉您使用“git add”开始跟踪。 我对这两个概念有点困惑,因为我假设跟踪文件的更改
为什么 git://有效 $ git clone git://github.com/schacon/grit.git Cloning into 'grit'... ... Checking conne
我在以下沙箱中练习 git:https://learngitbranching.js.org/?NODEMO 我在两个单独的 session 中运行了两组命令。第一组命令顺序如下: git clone
我是一名优秀的程序员,十分优秀!