How can I determine the status of a Git branch programmatically?

I read a few other SO posts and google search results that git status --porcelain is not really the command you want to rely on if you programmatically infer the current status of the git branch. In the end, I pointed out the rev-parse , diff-index and diff-files commands for this, but the method I'm currently using is a bit buggy, especially on branches other than master. Topics such as Bureau for oh-my-zsh seem to use git status --porcelain , which I mentioned above was not recommended by the git community. So what is the correct way to read branches like these in the statuses?

A segment of code from the Oh-My-ZSH theme in the Bureau so that he can understand what behavior I'm trying to reproduce.

 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 } 

In the end, I will support all of the above, here is my beginning on this and the basic commands that I now use to do something (sorry for the fact that Haskell, I hope this does not bother anyone from getting the essence of what the code does - no pun intended).

 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"] [] 

Change AndrewC noted that -porcelain is described in documents as intended for parsing by scripts. This makes me ask when to use rev-parse vs. --porcelain ??

+7
git parsing haskell
source share
1 answer

Only in this way is the official answer:

As in the comments, the D documents say that the -porcelain flag with Git Status contains parsing for the scripts. My source of confusion is that, in general, this is not the role of the porcelain flag, and traditionally the plumbing command in Git is usually indicated for this purpose. Thus, in this case, using the -porcelain flag seems to be an acceptable way to parse the state of Git repositories, but this is an exception to what is usually used as a parameter.

For more details, see the SO posts below, which I found when searching around for more detailed explanations. What does git rev-parse do? What does the term porcelain mean in Git?

+1
source share

All Articles