我阅读了各种SO帖子和Google搜索结果,发现如果您想以编程方式解析当前git分支状态,则不应该仅依赖于
以下是Bureau Oh-My-ZSH主题的代码片段,以便清楚地了解我要复制的行为。
git status --porcelain
命令。我最终找到了rev-parse
、diff-index
和diff-files
命令来完成这个任务,但我目前使用的方法有点错误,特别是在除master以外的分支上。像oh-my-zsh的Bureau主题似乎正在使用git status --porcelain
,但Git社区并不推荐这样做。那么,读取这些分支状态的正确方法是什么?以下是Bureau Oh-My-ZSH主题的代码片段,以便清楚地了解我要复制的行为。
bureau_git_status () {
_INDEX=$(command git status --porcelain -b 2> /dev/null)
_STATUS=""
if $(echo "$_INDEX" | grep '^[AMRD]. ' &> /dev/null); then
_STATUS="$_STATUS$ZSH_THEME_GIT_PROMPT_STAGED"
fi
if $(echo "$_INDEX" | grep '^.[MTD] ' &> /dev/null); then
_STATUS="$_STATUS$ZSH_THEME_GIT_PROMPT_UNSTAGED"
fi
if $(echo "$_INDEX" | command grep -E '^\?\? ' &> /dev/null); then
_STATUS="$_STATUS$ZSH_THEME_GIT_PROMPT_UNTRACKED"
fi
if $(echo "$_INDEX" | grep '^UU ' &> /dev/null); then
_STATUS="$_STATUS$ZSH_THEME_GIT_PROMPT_UNMERGED"
fi
if $(command git rev-parse --verify refs/stash >/dev/null 2>&1); then
_STATUS="$_STATUS$ZSH_THEME_GIT_PROMPT_STASHED"
fi
if $(echo "$_INDEX" | grep '^## .*ahead' &> /dev/null); then
_STATUS="$_STATUS$ZSH_THEME_GIT_PROMPT_AHEAD"
fi
if $(echo "$_INDEX" | grep '^## .*behind' &> /dev/null); then
_STATUS="$_STATUS$ZSH_THEME_GIT_PROMPT_BEHIND"
fi
if $(echo "$_INDEX" | grep '^## .*diverged' &> /dev/null); then
_STATUS="$_STATUS$ZSH_THEME_GIT_PROMPT_DIVERGED"
fi
echo $_STATUS
}
我最终将支持上述所有行为,但这是我的起点和我目前用于执行操作的基本命令(很抱歉它是Haskell,但希望这不会阻止任何人理解代码正在做什么-无意冒犯)。
hasCommitsToPush :: IO (Maybe Bool)
hasCommitsToPush = do
latestCommits <- liftM (fmap $ deleteNulls . splitOnNewLine) $ parseProcessResponse gitRemoteRefDiff
case latestCommits
of Nothing -> return Nothing
Just [] -> return $ Just False
Just [_] -> return $ Just True -- This case is for a new repository with the first commit in local but not yet pushed.
Just [latestRemoteCommit, latestLocalCommit] -> return . Just $ latestRemoteCommit /= latestLocalCommit
_ -> return Nothing
where gitRemoteRefDiff = readProcessWithExitCode "git" ["rev-parse", "@{u}", "HEAD"] []
hasStagedChanges :: IO (Maybe Bool)
hasStagedChanges = liftM (fmap isResponseNull) $ parseProcessResponse gitResponse
where gitResponse = readProcessWithExitCode "git" ["diff-index","--cached","--ignore-submodules","HEAD"] []
hasUnstagedChanges :: IO (Maybe Bool)
hasUnstagedChanges = liftM (fmap isResponseNull) $ parseProcessResponse gitStatus
where gitStatus = readProcessWithExitCode "git" ["diff-files","--ignore-submodules"] []
编辑 AndrewC指出,文档中描述了--porcelain用于脚本解析。这让我想问一个问题,何时应该使用rev-parse
而不是--porcelain
?
git status
手册描述--porcelain
标志的方式:以易于解析的脚本格式输出。这类似于短输出,但将在Git版本和用户配置不变的情况下保持稳定。 - jub0bs