Skip to main content

isCleanWorkingTree

Check whether the working tree is clean (no changes, tracked or untracked).

Function Signature

function isCleanWorkingTree(): Promise<boolean>

Returns

result
Promise<boolean>
true if the working tree is completely clean, false otherwise.

Example

if (await git.isCleanWorkingTree()) {
  console.log("Working tree is clean")
  // Safe to switch branches or pull
} else {
  console.log("Working tree has changes")
}

Use Cases

  • Pre-deployment checks
  • Branch switching validation
  • CI/CD pipeline guards
  • Automated release scripts
// Example: Safe branch switch
async function safeSwitchBranch(branch: string) {
  if (!await git.isCleanWorkingTree()) {
    throw new Error("Cannot switch: working tree has uncommitted changes")
  }
  
  await git.checkout(branch)
}

isDirty

Check whether the working tree has uncommitted changes.

Function Signature

function isDirty(
  opts?: IsDirtyOptions
): Promise<string>

Parameters

opts
IsDirtyOptions
Options controlling how the dirty state is evaluated.

Returns

result
Promise<string>
Returns the porcelain status output. An empty string means the working tree is clean. A non-empty string contains the status of changed files.

Examples

Check for any changes

const status = await git.isDirty()

if (status) {
  console.log("Working tree has changes:")
  console.log(status)
} else {
  console.log("Working tree is clean")
}

Check only tracked files

// Ignore untracked files
const status = await git.isDirty({ trackedOnly: true })

if (status) {
  console.log("Tracked files have been modified")
}

Parse dirty status

const status = await git.isDirty()

if (status) {
  const lines = status.split('\n').filter(Boolean)
  console.log(`${lines.length} files have changes`)
  
  // Show modified files
  const modified = lines.filter(line => line.startsWith(' M'))
  if (modified.length > 0) {
    console.log("Modified files:", modified.map(l => l.substring(3)))
  }
}

Comparison: isDirty vs isCleanWorkingTree

FunctionReturnsUse When
isCleanWorkingTree()booleanYou only need to know if clean/dirty
isDirty()stringYou need details about what changed
// Simple check
if (await git.isCleanWorkingTree()) {
  console.log("Clean!")
}

// Detailed check
const status = await git.isDirty()
if (status) {
  console.log("Changes detected:")
  console.log(status)
}

hasUntrackedFiles

Check whether the working tree contains untracked files.

Function Signature

function hasUntrackedFiles(): Promise<boolean>

Returns

result
Promise<boolean>
true if untracked files exist, false otherwise.

Example

if (await git.hasUntrackedFiles()) {
  console.log("There are untracked files in the working tree")
  
  // Get the list of untracked files
  const files = await git.getUntrackedFiles()
  console.log("Untracked:", files)
}

Use Cases

// Warn before switching branches
if (await git.hasUntrackedFiles()) {
  console.warn("Warning: You have untracked files that won't be switched")
}

// Pre-commit hook
if (await git.hasUntrackedFiles()) {
  const files = await git.getUntrackedFiles()
  console.log("Consider adding these files:")
  files.forEach(f => console.log(`  - ${f}`))
}

getUntrackedFiles

Get a list of untracked files in the working tree.

Function Signature

function getUntrackedFiles(): Promise<string[]>

Returns

result
Promise<string[]>
Array of untracked file paths.

Examples

List all untracked files

const untracked = await git.getUntrackedFiles()

if (untracked.length > 0) {
  console.log("Untracked files:")
  untracked.forEach(file => console.log(`  ${file}`))
} else {
  console.log("No untracked files")
}

Filter untracked files

const untracked = await git.getUntrackedFiles()

// Find untracked TypeScript files
const tsFiles = untracked.filter(f => f.endsWith('.ts'))
console.log(`${tsFiles.length} untracked TypeScript files`)

// Check for config files
const hasConfig = untracked.some(f => f.includes('config'))
if (hasConfig) {
  console.warn("Untracked config files detected")
}

Interactive add prompt

const untracked = await git.getUntrackedFiles()

if (untracked.length > 0) {
  console.log("Found untracked files:")
  untracked.forEach((file, i) => {
    console.log(`  ${i + 1}. ${file}`)
  })
  
  // In a real CLI, you'd prompt the user here
  const shouldAdd = confirm("Add all to staging?")
  
  if (shouldAdd) {
    await git.add(untracked)
    console.log("Files added to staging")
  }
}

Count by file type

const untracked = await git.getUntrackedFiles()

const byExtension = untracked.reduce((acc, file) => {
  const ext = file.split('.').pop() || 'no-extension'
  acc[ext] = (acc[ext] || 0) + 1
  return acc
}, {} as Record<string, number>)

console.log("Untracked files by type:")
for (const [ext, count] of Object.entries(byExtension)) {
  console.log(`  .${ext}: ${count}`)
}

Comparison Matrix

FunctionReturnsIncludes UntrackedIncludes ModifiedUse Case
isCleanWorkingTree()booleanYesYesQuick clean check
isDirty()stringYes (default)YesDetailed status
isDirty({ trackedOnly: true })stringNoYesIgnore untracked
hasUntrackedFiles()booleanYesNoCheck for untracked only
getUntrackedFiles()string[]YesNoList untracked files

Common Patterns

Pre-commit validation

async function validateBeforeCommit() {
  // Check for uncommitted tracked changes
  const status = await git.isDirty({ trackedOnly: true })
  if (!status) {
    throw new Error("No changes to commit")
  }
  
  // Warn about untracked files
  if (await git.hasUntrackedFiles()) {
    const files = await git.getUntrackedFiles()
    console.warn("Untracked files won't be included:")
    files.forEach(f => console.warn(`  - ${f}`))
  }
  
  return true
}

Clean state guard

async function requireCleanState(operation: string) {
  if (!await git.isCleanWorkingTree()) {
    throw new Error(
      `Cannot ${operation}: working tree has uncommitted changes. ` +
      `Commit or stash your changes first.`
    )
  }
}

// Usage
await requireCleanState("switch branches")
await git.checkout("main")

Smart status report

async function statusReport() {
  const clean = await git.isCleanWorkingTree()
  
  if (clean) {
    console.log("✓ Working tree is clean")
    return
  }
  
  const status = await git.isDirty({ trackedOnly: true })
  if (status) {
    const lines = status.split('\n').filter(Boolean)
    console.log(`! ${lines.length} tracked files modified`)
  }
  
  const untracked = await git.getUntrackedFiles()
  if (untracked.length > 0) {
    console.log(`! ${untracked.length} untracked files`)
  }
}

Build docs developers (and LLMs) love