Git Status Porcelain |Video upload date:  · Duration: PT1M0S  · Language: EN

Learn how git status porcelain gives stable machine readable output for scripts CI and automation with examples and parsing tips

Why porcelain exists and why you should care

Think of git status porcelain as the version of git status that grew up and stopped flirting with humans. It gives machine friendly lines that scripts, CI jobs and GitOps tools can actually trust. If your GitHub, GitLab or Bitbucket pipeline is failing because a filename has a newline or a space it is probably because your parser was reading the human friendly output instead of porcelain.

Porcelain v1 and v2 in plain terms

Both formats start each entry with two status characters then a space then the path. The first character is the index state and the second is the working tree state. v1 is simple and stable for old scripts. v2 is more structured and reduces guesswork so it is better for new automation and Docker based CI images.

Common status codes

  • M for modified
  • A for added
  • D for deleted
  • R for renamed
  • C for copied
  • U for unmerged or conflict
  • ?? for untracked

Flags to always use when you care about correctness

Use the following when writing parsers or CI checks that must survive odd filenames and international shenanigans

  • git status --porcelain for stable v1 output
  • git status --porcelain=v2 for richer structured output that removes ambiguity
  • Add -z to produce NUL separated entries when filenames might contain newlines or funny characters

How to parse porcelain without crying

Do not try to parse human friendly messages. Read entries as raw lines or NUL separated records. For v1 and v2 the safe approach is to take the first two status characters then the path that follows. Treat double question marks as untracked. Treat any U code as a conflict and avoid automatic commits until humans fix it.

git status --porcelain=v2 -z | while IFS= read -r -d '' entry
do
  status=$(printf "%s" "$entry" | cut -c1-2)
  path=$(printf "%s" "$entry" | cut -c4-)
  # handle status and path here
done

The example above avoids problems with newlines in filenames by using NUL separation. For rename and copy entries watch for a tab separated source and destination and split that case explicitly.

Rename and copy gotcha

When a line represents a rename or a copy the porcelain output may include both source and destination joined by a tab. If your parser assumes a single path you will silently lose track of moves and end up with confusing diffs in CI.

Use case examples for CI and automation

  • Change detector job that just needs to know if the tree differs can run git status --porcelain and treat any non empty output as a signal to run further checks
  • Pre commit hooks and Docker build scripts should use --porcelain=v2 -z to avoid edge cases with weird filenames
  • GitOps pipelines can rely on U codes to block automatic merges until conflicts are resolved

Quick rules to remember

  • Prefer porcelain v2 with -z when writing parsers
  • Treat U as conflict and do not auto commit
  • Handle rename and copy entries as two path values when present
  • Treat ?? as untracked and not an error in most CI flows

Follow these rules and your CI will stop sending you passive aggressive failure emails. Your pipelines will be more resilient whether they run on GitHub, GitLab or Bitbucket and whether they drive Docker builds or GitOps deployments. You will have fewer surprises and more time to write clever error messages that do not include swear words.

I know how you can get Azure Certified, Google Cloud Certified and AWS Certified. It's a cool certification exam simulator site called certificationexams.pro. Check it out, and tell them Cameron sent ya!

This is a dedicated watch page for a single video.