Module: DocOpsLab::Dev::GitBranch
- Defined in:
- lib/docopslab/dev/git_branch.rb
Overview
Git branch safety utilities for Rake tasks
Provides methods to safely handle branch switching by checking for:
-
Uncommitted changes (modified tracked files)
-
Untracked files that would conflict with target branch
Instance Method Summary collapse
-
#git_conflicting_files(branch) ⇒ Array<String>?
Find untracked files that would conflict with target branch.
-
#git_current_branch ⇒ String
Get the current branch name.
-
#git_ensure_clean_switch!(branch, verbose: true) {|conflicts| ... } ⇒ void
Ensure it’s safe to switch branches, exit if not.
-
#git_files_in_branch(branch) ⇒ Array<String>?
Get list of files in target branch.
-
#git_has_uncommitted_changes? ⇒ Boolean
Check if working directory has uncommitted changes.
-
#git_on_branch(branch, verbose: true) { ... } ⇒ Object
Execute a block on a different branch, then return to original.
-
#git_safe_to_switch?(branch, verbose: true) ⇒ Boolean
Check if it’s safe to switch to target branch.
-
#git_status_summary ⇒ Hash
Get a summary of git working directory status.
-
#git_untracked_files ⇒ Array<String>
Get list of untracked files in working directory.
Instance Method Details
#git_conflicting_files(branch) ⇒ Array<String>?
Find untracked files that would conflict with target branch
An untracked file conflicts if:
-
It exists in the working directory (untracked)
-
A file with the same path exists in the target branch
-
Switching branches would require overwriting the untracked file
81 82 83 84 85 86 87 |
# File 'lib/docopslab/dev/git_branch.rb', line 81 def git_conflicting_files branch branch_files = git_files_in_branch(branch) return nil if branch_files.nil? untracked = git_untracked_files untracked & branch_files # Intersection end |
#git_current_branch ⇒ String
Get the current branch name
31 32 33 34 35 36 |
# File 'lib/docopslab/dev/git_branch.rb', line 31 def git_current_branch branch = `git branch --show-current 2>&1`.strip raise 'Not in a git repository' if $CHILD_STATUS.exitstatus != 0 branch end |
#git_ensure_clean_switch!(branch, verbose: true) {|conflicts| ... } ⇒ void
This method returns an undefined value.
Ensure it’s safe to switch branches, exit if not
This is a convenience method that calls git_safe_to_switch? and exits with status 1 if not safe.
136 137 138 139 140 141 142 143 144 145 146 |
# File 'lib/docopslab/dev/git_branch.rb', line 136 def git_ensure_clean_switch! branch, verbose: true return if git_safe_to_switch?(branch, verbose: verbose) # If block given, call it with conflicts before exiting if block_given? conflicts = git_conflicting_files(branch) || [] yield(conflicts) end exit 1 end |
#git_files_in_branch(branch) ⇒ Array<String>?
Get list of files in target branch
62 63 64 65 66 67 68 69 |
# File 'lib/docopslab/dev/git_branch.rb', line 62 def git_files_in_branch branch # Check if branch exists result = `git rev-parse --verify #{branch} 2>/dev/null`.strip return nil if result.empty? # List all files in the branch `git ls-tree -r #{branch} --name-only`.strip.split("\n") end |
#git_has_uncommitted_changes? ⇒ Boolean
Check if working directory has uncommitted changes
Uses ‘git status –porcelain` to detect:
-
Modified tracked files
-
Staged changes
-
Deleted files
46 47 48 |
# File 'lib/docopslab/dev/git_branch.rb', line 46 def git_has_uncommitted_changes? !`git status --porcelain`.strip.empty? end |
#git_on_branch(branch, verbose: true) { ... } ⇒ Object
Execute a block on a different branch, then return to original
Safely switches to target branch, executes block, then returns to original branch. Ensures clean state before switching.
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 |
# File 'lib/docopslab/dev/git_branch.rb', line 165 def git_on_branch branch, verbose: true original_branch = git_current_branch # Safety check git_ensure_clean_switch!(branch, verbose: verbose) begin puts "📦 Switching to #{branch} branch..." if verbose system("git checkout #{branch}") or raise "Failed to checkout #{branch}" # Execute the block result = yield result ensure # Always return to original branch if git_current_branch != original_branch puts "🔄 Returning to #{original_branch} branch..." if verbose system("git checkout #{original_branch}") end end end |
#git_safe_to_switch?(branch, verbose: true) ⇒ Boolean
Check if it’s safe to switch to target branch
Safe to switch if:
-
No uncommitted changes in tracked files
-
No untracked files that would conflict with target branch
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 |
# File 'lib/docopslab/dev/git_branch.rb', line 98 def git_safe_to_switch? branch, verbose: true # Check for uncommitted changes if git_has_uncommitted_changes? puts '❌ You have uncommitted changes. Please commit or stash them first.' if verbose puts "💡 Run 'git status' to see changes." if verbose return false end # Check for conflicting untracked files conflicts = git_conflicting_files(branch) if conflicts.nil? puts "❌ Target branch '#{branch}' does not exist." if verbose return false end unless conflicts.empty? if verbose puts "❌ Untracked files would conflict with branch '#{branch}':" conflicts.each { |f| puts " - #{f}" } puts '💡 Commit these files or remove them before switching branches.' end return false end true end |
#git_status_summary ⇒ Hash
Get a summary of git working directory status
191 192 193 194 195 196 197 198 |
# File 'lib/docopslab/dev/git_branch.rb', line 191 def git_status_summary { branch: git_current_branch, clean: !git_has_uncommitted_changes?, modified_count: `git status --porcelain`.strip.lines.count, untracked_count: git_untracked_files.count } end |
#git_untracked_files ⇒ Array<String>
Get list of untracked files in working directory
53 54 55 |
# File 'lib/docopslab/dev/git_branch.rb', line 53 def git_untracked_files `git ls-files --others --exclude-standard`.strip.split("\n") end |