Ever fallen in love with a shiny new tool so much that you start using it for everything? That’s exactly what happened to me with AI. Like a child with a new toy, I was throwing AI at practically every problem I encountered—including ones that didn’t really need it. Somewhere along the way, I’d forgotten my scripting roots and the elegant simplicity they offer.
When Git Gets Complicated: A Tale of Branch Strategies
I was recently working on a PowerShell project with incredibly specific Git requirements. We had strict branch naming conventions tied to JIRA tickets, different rules for different file types, and precise formatting requirements for commit messages. Even seasoned developers on our team would occasionally mess up the workflow.
Rather than writing up documentation that nobody would read, I thought I’d automate the process. And since AI was my go-to solution for everything these days, I decided to create an AI rule file to handle all our Git operations.
# Git Version Control Rules and Requirements This PowerShell project uses a Git repository in the workspace and has specific rules for branching and Git commits you must follow. ## Important General Instructions that apply to all Git commits 1. Do not commit any changes unless asked. 2. Always ask for confirmation before commiting any code. 3. Before committing any changes to a local branch, always first pull from the remote master branch to get the latest changes and merge them into your current working branch. After ensuring your branch is up-to-date with master and any conflicts are resolved, you can then commit your changes to your local working branch. 4. Always check for any staged changes and assume the user wants to commit these. If there are unstaged changes, always ask the user if they'd like to include those also. 5. Unless specified by the user, always look at the changes made and come up with a descriptive commit message. 6. When a local commit is complete, always ask the user if they'd like to push to the remote repo. ## Version Control Rules by File Type There are three distinct categories of changes you need to be aware of. Each category has it's own requiremnets you must adhere to. ### Pester Test Code Changes All files located in `/..../PesterTests` are Pester tests. All commits for these files require th Git branch to be on `....`. The `....` is the name of the associated JIRA ticket for all Pester test changes. Do not allow the user or yourself to commit changes to any other branch when making changes to Pester tests other than the `.....` branch. Never commit a change to a C# source code file to the `....` branch. All commmit messages that change Pester tests must contain the JIRA issue (...), the commit message and `...`. For example: `[...] ...` ### PowerShell Cmdlet Changes All files located in in any folder other than `...` are considered PowerShell cmdlet source files. All changes to these files must have an associated JIRA ticket number and branch. Any change to PowerShell cmdlet source must be done in a branch called `...`. If the user has not provided a JIRA issue for the commit and changes to C# source code files are necessary, do not commit the chnage. All commit messages for PowerShell cmdlet source code must contain the specific JIRA issue number, commit message and `CR:none` e.g. `...` Never allow a change to a PowerSHell cmdlet source file without an associated JIRA ticket number. ## Pull Requests When requested to perform a pull request (ONLY UPON REQUEST), you must always create the pull request in the form: `[] CR:none` and assign the reviewer of the PR to ... and the an assignee of adbertram. You can create PRs via the Github CLI. ## Required Workflow for Git Changes. When asked to commit changes: 1. Discover the type of files involved in pending changes (Pester tests or PowerShell Cmdlet Code). 2. Check the branch you're currently on. 3. If any Pester tests are pending changes: - If you're not on the required branch (`....`): - Stash all changes. - Switch to the `...` branch. - Pull the latest changes from the remote `....` branch (if it exists and has been pushed before). - Pull the latest changes from the remote main branch (e.g., master, main, develop) and merge them into `....`. Resolve any merge conflicts. - Unstash ONLY Pester test files. If unstashing causes conflicts with the merged changes from main, resolve them. - Commit changes following all commit message rules. - If you are on the required branch (`...`): - Pull the latest changes from the remote `....` branch (if it exists and has been pushed before). - Pull the latest changes from the remote main branch (e.g., master, main, develop) and merge them into `....`. Resolve any merge conflicts. - Stage ONLY Pester tests and commit changes following all commit message rules. 4. If any changes are to PowerShell Cmdlet/C# source code files: - If not already known, ask the user what JIRA ticket you should use for these changes. - If you're not on the required branch (`....`): - Stash all changes. - Switch to or create the required feature branch (e.g., `....`). It's good practice to base new feature branches off the latest main branch. - Pull the latest changes from the remote counterpart of this feature branch (if it exists and has been pushed before). - Pull the latest changes from the remote master branch and merge them into the current feature branch. Resolve any merge conflicts. - Unstash ONLY PowerShell Cmdlet/C# source code files. If unstashing causes conflicts with the merged changes from main, resolve them. - Commit changes following all commit message rules. - If you are on the required branch: - Pull the latest changes from the remote counterpart of this feature branch (if it exists and has been pushed before). - Pull the latest changes from the remote main branch (e.g., master, main, develop) and merge them into the current feature branch. Resolve any merge conflicts. - Stage ONLY PowerShell Cmdlet/C# source code files and commit changes following all commit message rules.
Did it work? Sure, most of the time. But there were always those frustrating edge cases—commit messages formatted slightly wrong, branch switching happening in the wrong order, or the AI deciding to commit changes despite my explicit rule #1: “Do not commit any changes unless asked.“
AI, it turns out, can be as stubborn as a determined toddler sometimes.
The Lightbulb Moment: Back to Basics
Then it hit me. Why was I using AI—with all its creative unpredictability—for a process that should be 100% predictable? The solution was staring me in the face all along:
When you need to commit a change via Git, run the script git_workflow.sh.
One simple line replaced pages of AI instructions. I crafted a Bash script that handled everything my AI rules were trying to do, but with perfect consistency:
#!/bin/bash # This script automates the Git workflow for aPowerShell project according to version control requirements set -e # Exit on any error # Colors for output RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[0;33m' BLUE='\033[0;34m' NC='\033[0m' # No Color # Configuration PESTER_TEST_PATH="PowerShell/PesterTests" PESTER_BRANCH="...." MAIN_BRANCH="master" # Change to master or main if needed WORKSPACE_ROOT="...." # Change to workspace root cd "$WORKSPACE_ROOT" <--SNIP--> # Ask for commit message read -p "Enter a brief description for the source code changes: " SOURCE_MESSAGE COMMIT_MESSAGE="[xxxxx-$JIRA_NUMBER] $SOURCE_MESSAGE CR:none" # Commit changes print_message $BLUE "Committing source code changes with message: $COMMIT_MESSAGE" git commit -m "$COMMIT_MESSAGE" fi # Ask if user wants to push changes if confirm "Would you like to push these changes to the remote repository?"; then CURRENT_BRANCH=$(git branch --show-current) print_message $BLUE "Pushing changes to origin/$CURRENT_BRANCH..." git push -u origin "$CURRENT_BRANCH" print_message $GREEN "Changes pushed successfully!" else print_message $YELLOW "Changes committed locally but not pushed to remote." fi print_message $GREEN "Git workflow completed successfully!"
Wait—did I say I crafted this script? That’s not entirely accurate. My Bash skills have gathered a fair bit of rust over the years, so I actually asked AI to help write it. The difference? Instead of asking AI to perform a complex process repeatedly, I asked it to create a tool that reliably perform that process.
And that’s when I had my epiphany.
The Hammer and Nail Syndrome
I’d fallen victim to the classic “when all you have is a hammer, everything looks like a nail” syndrome. AI had become my shiny new hammer, and I was hammering away at problems that might have been better handled with a screwdriver—or in this case, a good old-fashioned script.
In my defense, it’s easy to get swept up in the AI revolution. Natural language interfaces make everything so accessible that we can forget other approaches exist. A year ago, I probably would have thought “script” immediately. Now, my first instinct is to prompt an AI.
To be fair to myself, I couldn’t have just asked AI to generate that Git script out of the blue. I could only create it because I had already defined the entire process in my rule file. I had done all the hard work of defining the workflow; I just couldn’t see the forest for the trees when choosing the proper implementation.
The Right Tool for the Right Job
This experience reminded me of a fundamental principle: AI might not be the optimal solution if a process can be clearly defined with specific steps and predictable outcomes. Here’s why scripts often outshine AI for deterministic tasks:
Scripts: The Reliable Workhorses
-
- Consistency and Reliability: Scripts perform the same way every single time. Give them the same input, and you’ll get the same output—no surprises. Conversely, AI thrives on creative variations that can be problematic when you need absolute consistency.
- Resource Efficiency: Running a local script uses minimal resources compared to making API calls to an AI model. This difference becomes significant with frequent operations.
- Debugging Made Simple: When a script misbehaves, you can pinpoint the exact line causing trouble. With AI, troubleshooting feels more like psychoanalysis than programming.
- Version Control: Scripts can be versioned, tested, and rolled back with standard tools. AI prompts often exist as text blobs that evolve haphazardly over time.
AI: The Creative Problem Solver
That’s not to say AI doesn’t have its place. AI truly shines when:
-
- You’re deciphering natural language with all its messy nuances
- You need to identify patterns in complex, unstructured data
- Creative solutions or content generation are required
- Requirements are ambiguous or still evolving
Scripts: The Methodical Executors
On the flip side, reach for a script when dealing with:
-
- File operations and predictable data transformations
- Automated system tasks that follow clear patterns
- Data validation where the rules don’t change
- Repeatable business processes with well-defined steps
Finding the Sweet Spot: A Hybrid Approach
The most effective approach combines the strengths of both tools. Here’s my new workflow:
- Define Your Process First: Thoroughly document your workflow before reaching for any tool. What are the steps? What are the rules? What are the expected outcomes?
- Identify Decision Points: Determine where genuine decision-making is needed versus simple if/then logic. This helps determine where AI might add value.
- Consider Long-Term Maintenance: Consider who will maintain the solution and how updates will be handled. Scripts have a clear advantage here.
- Use AI as a Co-Creator: Once you have a well-defined process, AI can help create the initial script or optimize certain aspects, just as it helped me with the Bash script.
Remember: AI is a powerful amplifier of human capabilities, not a replacement for thoughtful process design.