2015-01-30 4 views
7

Я прочитал различные другие сообщения SO и результаты поиска Google, которые git status --porcelain - это не настоящая команда, на которую вы хотите положиться, если вы разыгрываете текущий статус ветки git программным способом. В конце концов я указал на rev-parse, diff-index и diff-files команды для этого - однако метод, который я использую в настоящее время, немного глючит, особенно на ветвях, кроме мастера. Темы, такие как Bureau for oh-my-zsh, похоже, используют git status --porcelain, о которых я говорил выше, не был рекомендован сообществом Git. Итак, каков правильный способ чтения в таких статусах таких филиалов, как эти?Каким образом можно определить статус ветви Git программно?

Сегмент кода из темы 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 ??

+4

В документации для 'git status -porcelain' явно указано, что он предназначен для анализа синтаксическими сценариями. Без описания того, в какой ситуации вы плохо обращаетесь, трудно сказать, что не так с вашим подходом. Я бы предположил, что вы не обрабатываете не отслеживающие ветви правильно. –

+0

@AndrewC Это вызывает вопрос, почему я читаю (или помню чтение) ответы, говорящие, что -porcelain не был таким, а затем продолжал рекомендовать команды, такие как rev-parse. Я бы подумал, что сошел с ума, за исключением того, что -процедура была самым очевидным подходом, но я отказался от нее из-за этих предложений, как показывает мой код. Хммм. – josiah

+4

Связанные: [Библиотека Haskell для управления git repo] (http://stackoverflow.com/q/6609643/279627) –

ответ

1

Просто так есть официальный ответ:

Как и в комментариях, то документы DO сказать, что --porcelain флаг с Git Status есть для обеспечения разбора скриптов. Мой источник путаницы заключается в том, что в целом это не роль фарфорового флага, и традиционно для этой цели в Git обычно указывается команда «сантехника». Таким образом, в этом случае использование флага -porcelain представляется приемлемым способом разбора статуса репозиториев Git, но это исключение из того, что обычно означает.

Более подробная информация приведена в нижеприведенных сообщениях СО, которые я обнаружил при поиске вокруг, чтобы получить более подробные объяснения. What does git rev-parse do? What does the term "porcelain" mean in Git?

Смежные вопросы