Git Plumbing vs Porcelain Commands

Summary:
Understand the low-level (plumbing) and high-level (porcelain) commands.


Git is an incredibly powerful distributed version control system. As you dig deeper into its inner workings, you may come across two terms: plumbing and porcelain. These metaphors, coined by Git’s creator Linus Torvalds, refer to the two broad classes of commands in Git. Knowing the difference empowers you to troubleshoot issues, automate workflows, and better understand what's happening under the hood.

In this article, we'll dive into what plumbing and porcelain commands mean, explore examples of each, and discuss when and why you might want to use them.

What are Plumbing and Porcelain Commands?

Porcelain Commands (High-Level)

Porcelain commands are the familiar, user-facing commands. They're designed to be easy to use and provide a user-friendly interface for common Git operations. Think of them as the pretty, clean outer surface of your version control system: the porcelain on your bathroom fixtures that's comfortable to touch.

Examples:

  • git add
  • git commit
  • git status
  • git push
  • git pull
  • git clone
  • git branch
  • git checkout
  • git merge

Porcelain commands do a lot of work behind the scenes to make your workflow as intuitive as possible. They handle details like object creation, index management, and more.

Plumbing Commands (Low-Level)

Plumbing commands are the low-level, internal commands that Git porcelain commands often use behind the scenes. They’re powerful, precise, but not always intuitive or user-friendly. These commands expose Git’s under-the-hood objects and mechanisms—the plumbing that makes everything flow.

Examples:

  • git hash-object
  • git cat-file
  • git update-index
  • git write-tree
  • git ls-tree
  • git read-tree
  • git rev-parse
  • git update-ref

Plumbing commands are generally stable and designed to be scripted or used by other programs, not necessarily by end-users during daily work.

Analogy: A Plumbing and Porcelain Bathroom

Torvalds' metaphor is perfect: in your bathroom, porcelain is what you touch—the sink and the toilet—but all the real work is handled by the plumbing out of sight. Most people interact with the porcelain, but the plumbing is essential to making the whole thing function.

Similarly, most Git users stick with porcelain commands, but power users and tooling authors may sometimes dip into the plumbing for more control.

Why Does This Distinction Matter?

When to Use Porcelain

If you are:

  • Making everyday commits and merges
  • Navigating branches or repositories
  • Collaborating with others
  • Unfamiliar with Git internals

Just stick with porcelain commands. They protect you from accidental data loss, take care of housekeeping, and (usually) only show you what you need.

When to Use Plumbing

Consider using plumbing commands when:

  • You are scripting custom Git workflows
  • You need granular control over repository objects and references
  • You’re debugging tricky problems
  • You want to understand or manipulate Git's raw data structures

For example, a script to gather commit statistics might use git rev-list and git cat-file to enumerate and examine objects directly.

Note: While plumbing commands are powerful, they can also be dangerous. They don't protect you from mistakes and won’t warn you about overwriting or deleting important data.

Examples: Porcelain vs Plumbing

Let’s see how you might perform a simple operation using both approaches:

Adding a File to the Repository

  • Porcelain:

    git add README.md
    git commit -m "Add README"
    
  • Plumbing:

    # Store the file in the object database
    git hash-object -w README.md
    
    # Add the file to the index
    git update-index --add README.md
    
    # Write the current index as a new tree
    git write-tree
    
    # Create a new commit object
    git commit-tree <tree_hash> -m "Add README"
    

As you can see, the plumbing approach is much more involved and exposes the process that git add and git commit perform under the hood.

Viewing Commit Content

  • Porcelain:

    git show <commit>
    
  • Plumbing:

    # Get tree hash of the commit
    git cat-file commit <commit>
    # Then, show content of tree or blob
    git cat-file -p <tree_or_blob_hash>
    

A List of Common Plumbing vs Porcelain Commands

Porcelain Plumbing Purpose
git add git update-index Add file to staging area (index)
git commit git commit-tree Record changes in the repository
git log git rev-list Show commit history
git status (no direct equiv) Show repository status
git checkout git read-tree Update working directory
git branch git update-ref Manage branch references
git show git cat-file Display object contents

Tips for Using Plumbing Commands

  • Always make backups. Plumbing commands can alter data irreversibly.
  • Use in scripts, not manually. Scripted use reduces the chance of mistakes.
  • Consult the documentation. Plumbing commands have many options and expect exact input/output formats.

Conclusion

Whether you stick to the comfort of porcelain or occasionally need the flexibility of plumbing, understanding the distinction reveals much about how Git works. For day-to-day work, keep to porcelain commands—they’re safer and more user-friendly. When you need full control, or are creating powerful workflows, plumbing commands let you harness Git’s true power.

Either way, the combination of both is what makes Git so versatile—a tool for casual users and power users alike.


Further Reading:

Happy Gitting!