megacolorboy

Abdush Shakoor's Weblog

Writings, experiments & ideas.

Removing Commits from a Branch Using Git Interactive Rebase

I'm working on a project that had approximately five minor incident fixes. However, I got approval from the client side to push only three of them. Luckily, my commits are atomic, so making this build was easier than I thought.

At this moment, I decided to clone the latest branch into a temporary branch and roll back two commits for today's deployment while keeping the latest branch intact with all the fixes.

To achieve this, I used Git interactive rebase, a powerful tool for modifying commit history.

Why Use Interactive Rebase?

Interactive rebase allows you to modify commit history, including:

  • Removing unwanted commits
  • Reordering commits
  • Squashing multiple commits into one
  • Editing commit messages

How I Did It?

Here’s the step-by-step process I followed:

1. Clone the Branch

Before making any changes, I cloned the branch to have a backup:

git checkout -b my-cloned-branch original-branch

2. Start Interactive Rebase

To remove specific commits, I ran:

git rebase -i HEAD~N

Where N is the number of commits I wanted to review. This opened an editor displaying the most recent commits.

3. Modify the Commit List

The interactive rebase interface showed something like this:

pick abc123 Commit message 1
pick def456 Commit message 2
pick ghi789 Commit message 3

To remove a commit, I replaced pick with drop.

To edit or squash commits, I could replace pick with commands like edit or squash.

After making my changes, I saved and closed the editor.

4. Handle Any Conflicts (If Needed)

If Git encountered conflicts, it prompted me to resolve them. I fixed the files and continued the rebase:

git rebase --continue

Key Takeaways

  • Interactive rebase is powerful for cleaning up commit history.
  • Always clone or create a backup branch before rebasing.
  • If working with a team, communicate before modifying shared branches.

This was a great learning experience, and now I feel more confident managing Git history efficiently!

Hope you found this tip useful!

Recovering MySQL After an Accidental Binlog Deletion

Last night, I found myself debugging a MySQL issue at an ungodly hour. The MySQL80 service refused to start, throwing a vague error:

The MySQL80 service started and then stopped…

Digging into mysql.err, I discovered the culprit—someone (not me! 😤) had accidentally deleted a binary log (mysql-bin.000xxx) while MySQL was still tracking it. Since MySQL relies on binlogs for replication and crash recovery, it panicked when it couldn't find the missing file.

The Fix

To get MySQL running again, I had to:

  • Disable binary logging (since this is a standalone server)
  • Delete the corrupt binlog index file (mysql-bin.index)
  • Purge all old binlog files that were hogging disk space

How to Properly Disable Binary Logging in MySQL 8.0?

Since MySQL 8.0 enables binlogs by default, simply removing log-bin=mysql-bin from my.ini wasn’t enough. I had to:

Comment out the existing binlog setting in my.ini

# log-bin=mysql-bin

Explicitly disable binary logging

[mysqld]
skip-log-bin

Delete the old mysql-bin.index file

  • This file keeps track of all binary log files.
  • Since a referenced binlog file was deleted, MySQL would fail to start if the index still contained entries for missing files.
  • Deleting it ensures that MySQL doesn’t look for non-existent logs.

After restarting the service, I confirmed binlogging was off with:

SHOW VARIABLES LIKE 'log_bin';

Output:

log_bin | OFF

In conclusion, crisis averted, disk space reclaimed and finally got some sleep. 😴

Hope you found this useful!

9 Software Books I'm Reading This Year to Become a Better Engineer

As a software engineer, continuous learning is essential. The tech industry evolves rapidly, and keeping up requires a commitment to improving skills, refining best practices, and understanding the deeper principles behind great software design. This year, I’ve curated a list of nine must-read books that will help me become a better developer, architect, and problem solver.

If you're looking to level up your software engineering skills, these books might interest you too:

The Pragmatic Programmer

By Andrew Hunt & David Thomas

"Care about the code you write and the people who will maintain it after you."

A foundational book that every developer should read. It provides practical advice on coding, debugging, and automation, making you a more adaptable and efficient engineer.

Designing Data-Intensive Applications

By Martin Kleppmann

"A well-designed system grows gracefully as the dataset, traffic volume, or complexity increases."

A must-read for backend engineers and system architects, this book explores data modeling, distributed systems, and scalability challenges.

Clean Code

By Robert C. Martin

"Indeed, the ratio of time spent reading versus writing is well over 10 to 1. We are constantly reading old code as part of the effort to write new code."

Writing clean, maintainable code is a core skill for developers. This book offers practical techniques for improving code quality.

The Mythical Man-Month

By Frederick P. Brooks Jr.

"Adding manpower to a late software project makes it later."

A classic in software project management, this book explains why adding more people to a late project only makes it later.

Refactoring

By Martin Fowler

"Any fool can write code that a computer can understand. Good programmers write code that humans can understand."

A practical guide to improving existing code without altering its functionality, making it more readable and maintainable.

Domain-Driven Design

By Eric Evans

"The heart of software is its ability to solve domain-related problems for users."

This book teaches how to align software design with business logic, making complex software systems more manageable.

Working Effectively with Legacy Code

By Michael Feathers

"To change software means to change behavior. Our goal is to do so safely."

If you’ve ever had to deal with old, complex codebases, this book provides strategies for refactoring without breaking functionality.

Why Programs Fail

By Andreas Zeller

"Every bug has a cause, and every cause has a cure."

A systematic approach to debugging, helping developers diagnose and fix software defects effectively.

Extreme Ownership

By Jocko Willink & Leif Babin

"Leaders must own everything in their world. There is no one else to blame."

Leadership and accountability are critical for engineers working in teams. This book teaches how taking full responsibility leads to success.

Final Thoughts

These books cover a wide spectrum of skills—from writing clean code and designing scalable systems to debugging, refactoring, and leadership. By reading and applying the lessons in these books, I aim to become a better software engineer this year.

How to Revert a Git Commit on the Server?

Today I learned how to revert a Git commit after pulling it on a server. Whether you've made a mistake or just need to backtrack, Git offers several ways to undo commits depending on your situation. Here's a quick guide on how to handle it.

If You Haven't Pushed the Commit Yet

If the commit hasn't been pushed to the remote repository, you can use git reset to undo it.

Soft Reset (keeps changes staged)

git reset --soft HEAD~1

This moves the HEAD back by one commit but keeps your changes staged.

Mixed Reset (keeps changes unstaged):

git reset --mixed HEAD~1

This moves the HEAD back by one commit and unstages your changes.

Hard Reset (discards changes):

git reset --hard HEAD~1

This completely removes the last commit and discards any changes.

Tip: Replace HEAD~1 with HEAD~2 to go back two commits, and so on.

If You've Already Pushed the Commit

Revert the Commit (Safe for Shared Repositories):

If you've already pushed the commit and want to undo it without rewriting history, use git revert. This creates a new commit that undoes the changes.

git revert <commit_hash>

Find the commit hash using:

git log --oneline

Force Reset (If You're Okay Rewriting History):

If you don't mind rewriting history (and no one else is working on the branch), you can force reset.

git reset --hard <commit_hash>
git push origin HEAD --force

⚠️Warning

This is not recommended if others are working on the same branch as it can cause conflicts.

If You Just Pulled and Want to Undo That

If you just pulled and want to undo the merge, you can reset to the previous state using ORIG_HEAD.

Undo a Merge Pull:

git reset --hard ORIG_HEAD

This will bring your repository back to the state before the last pull.

Final Thoughts

Reverting commits can seem daunting at first, but once you understand the tools Git offers, it's pretty straightforward. Always double-check before using --hard or --force to avoid accidental data loss!

Hope this helps you get back on track!

How to Delete Multiple Git Branches from the Command Line?

Whether you're cleaning up local branches after a feature merge or tidying up remote branches, here’s how you can do it.

Deleting Multiple Local Branches

To delete multiple local branches safely (only if they’ve been merged), use:

git branch -d branch1 branch2 branch3

If the branches haven't been merged and you still want to delete them, force delete with:

git branch -D branch1 branch2 branch3

Deleting Multiple Remote Branches

For remote branches, you can delete them by running:

git push origin --delete branch1 branch2 branch3

Alternatively, you can use the colon : syntax:

git push origin :branch1 :branch2 :branch3

Deleting Multiple Branches Using a Pattern

If you want to delete branches that follow a naming pattern (like feature/ branches), you can use grep and xargs:

For local branches:

git branch | grep 'feature/' | xargs git branch -d

To force delete:

git branch | grep 'feature/' | xargs git branch -D

For remote branches:

git branch -r | grep 'origin/feature/' | sed 's/origin\///' | xargs -I {} git push origin --delete {}

Final Tips

  • List branches before deleting: Use git branch for local and git branch -r for remote branches to verify which ones you’re about to delete.
  • Be cautious with force delete (-D): It will remove branches even if they haven’t been merged, so make sure you won’t lose important work.

Hope you found this useful!

Laravel Scopes vs. Builder Queries: Which Should You Use?

If you're building a Laravel application, you're probably spending a lot of time writing queries. And as your project grows, you'll inevitably face this question: Should I use scopes or builder queries? While both have their place, choosing the right tool for the job can make a world of difference. Here's my opinionated take on the matter.

The Case for Scopes

Scopes are, quite simply, one of Laravel's hidden gems. They let you encapsulate common query logic within your models, making your code clean, reusable, and easy to read. Think of them as tiny, purposeful functions designed to save you time and sanity.

Take this example:

<?php
    // In your model
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    // Usage
    $activeUsers = User::active()->get();
?>

Suddenly, instead of littering your controllers with where('status', 'active') everywhere, you have a single, reusable method that reads like English. Scopes shine when you need commonly used filters like active, published, or recent. They’re easy to use, they’re consistent, and they make your code feel more intuitive.

Why I Prefer Scopes for Reusability

Here’s the thing: in any sizable Laravel app, you’ll inevitably find patterns in your queries. Rewriting the same query logic over and over? That’s a code smell. By using scopes, you centralize your query logic, reducing redundancy and improving maintainability.

For example:

<?php
    $pubishedPosts = Post::published()->recent()->get();
?>

This reads beautifully and keeps your codebase DRY (Don’t Repeat Yourself). If the definition of "published" or "recent" changes, you only need to update it in one place. Scopes turn repetitive query logic into single lines of magic.

The Case for Builder Queries

That said, not everything belongs in a scope. Some queries are just too specific, too complex, or too dynamic. This is where builder queries come in.

Imagine you’re building a report that requires multiple joins, conditional logic, or dynamic filters. Scopes could become unwieldy here. Instead, a well-crafted builder query in your controller, service, or repository might make more sense:

<?php
    $users = User::where('status', 'active')
        ->whereDate('created_at', '>', now()->subDays(30))
        ->orderBy('created_at', 'desc')
        ->get();
?>

Builder queries are perfect for:

  • One-off operations.
  • Highly dynamic queries.
  • Scenarios where scopes would make your models bloated or overly complex.

The flexibility of builder queries is unmatched. You can construct them on the fly, adapt them to user inputs, and handle edge cases without worrying about making your models an unreadable mess.

My Opinionated Take: Use Scopes as a Default, Builder Queries for the Edge Cases

If I had to pick a side, I’d say: lean on scopes as your default tool, and reserve builder queries for those rare cases when scopes just don’t cut it. Why?

  1. Scopes enhance readability. Your queries read like sentences, and your intentions are crystal clear.
  2. Scopes promote DRY principles. They’re reusable and encapsulate logic, which makes future maintenance a breeze.
  3. Builder queries are powerful but can become messy. Unless you’re careful, a complex query in your controller can grow into a sprawling monstrosity. Keep your controllers lean and delegate to scopes or dedicated query classes where possible.

When Not to Use Scopes

There are times when using a scope might do more harm than good:

  • Too much complexity: If a scope needs multiple parameters or involves complex joins, it’s better suited as a custom query builder or a dedicated repository method.
  • Rarely used logic: Don’t clutter your models with scopes for queries that are only needed once or twice.
  • Dynamic, user-driven queries: When filters are highly variable, builder queries give you the flexibility you need.

Conclusion: Balance Is Key

Laravel gives you powerful tools to write queries, and both scopes and builder queries have their roles. Use scopes to simplify and centralize reusable logic, and reach for builder queries when flexibility and complexity demand it. By balancing both, you’ll keep your codebase clean, maintainable, and a joy to work with.

So, what’s your take? Are you a scope enthusiast or a builder query champion? Either way, Laravel’s got you covered.

A Starter Guide to Software Version Control

Version Control Systems (VCS) are indispensable tools for modern software development. When I first started working with version control, I was overwhelmed by the terminology and the various workflows. Over time, I realized that mastering VCS isn't just about understanding commands—it's about adopting practices that make development smoother and more collaborative. In this post, I’ll share my journey, the lessons I’ve learned, and a practical approach to version control that works for teams of any size.

What is Version Control?

I remember my first experience losing hours of work because I accidentally overwrote a file. That’s when I discovered the magic of version control. It’s like having a time machine for your code! At its core, version control tracks and manages changes to your software code. Here’s why it’s essential:

  • Collaborate with ease: Gone are the days of emailing files back and forth. Multiple developers can work on the same codebase without stepping on each other’s toes.
  • Track every change: With a detailed history of changes, debugging becomes less of a nightmare.
  • Rollback anytime: If something breaks, you can revert to a stable version in seconds.

Today, tools like Git, Subversion (SVN), and Mercurial are popular choices, with Git leading the pack. If you haven’t tried Git yet, you’re missing out on a developer’s best friend.

Key Concepts

Here’s a quick glossary that helped me when I was starting out:

  1. Repository: Think of this as your project’s home. It stores your code and its entire version history.
  2. Commit: A snapshot of your code changes. A good commit is like leaving breadcrumbs for your future self or teammates.
  3. Branch: This was a game-changer for me. Branches let you work on new features or fixes without touching the main codebase.
  4. Merge: When you’re ready to bring your work back into the main project, merging combines it with the existing code.
  5. Tag: These are like bookmarks, marking specific points in your project’s history—perfect for releases.

Types of Branches

When I joined my first team project, I was introduced to a branching strategy that revolutionized the way I worked. Here’s how it breaks down:

1. Main Branches

  • Main (main or master): This is the crown jewel—the stable, production-ready branch. It’s sacred territory where only thoroughly tested code belongs.
  • Development (dev): This is where the magic happens. New features and fixes are integrated and tested here before they’re ready for production.

2. Feature Branches

When you’re working on something new, create a feature branch. Here’s how it works:

  • Purpose: To develop a specific feature.
  • Workflow: Start from dev, and when you’re done, merge back into dev.
  • Naming Convention: feature/new-login-system

3. Release Branches

Preparing for a new release? Here’s what you do:

  • Purpose: To finalize a version for production.
  • Workflow: Start from dev, do final testing and fixes, then merge into main.
  • Naming Convention: release/v1.0

4. Hotfix Branches

Production bugs can’t wait. That’s where hotfix branches save the day:

  • Purpose: To fix critical issues in production.
  • Workflow: Start from main, fix the issue, then merge into both main and dev.
  • Naming Convention: hotfix/login-bugfix

A Practical Workflow Example

Here’s a typical workflow I follow:

  1. Feature Development: Let’s say I’m building a new login system. I’d create a branch called feature/new-login-system off dev. Once the feature is complete and tested, I merge it back into dev.
  2. Preparing for Release: When it’s time to launch, I’d create a branch called release/v1.0 from dev. After some final tweaks, I merge it into main and tag it as v1.0.
  3. Production Hotfix: If a bug pops up in v1.0, I’d create a branch called hotfix/login-bugfix from main. Once fixed, I’d merge it into both main and dev and tag it as v1.0.1.

Best Practices

Here are some lessons I learned the hard way:

  1. Write Clear Commit Messages: Your future self will thank you. A good message explains what changed and why.
  2. Keep Commits Small: Each commit should represent a single, logical change. This makes debugging a breeze.
  3. Review Before Merging: Always use pull requests or merge requests. Two heads are better than one.
  4. Use Tags for Releases: Tags are lifesavers when you need to rollback or track changes.
  5. Backup Your Repository: This might sound obvious, but don’t take it for granted.

Why Version Control is a Game-Changer?

For me, version control transformed how I approach coding. It made collaboration smoother, debugging faster, and deployments safer. Whether you’re working solo or with a team, adopting a thoughtful version control strategy is a must.

Final Thoughts

Version control is more than just a tool—it’s a mindset. By following the practices and strategies outlined here, you’ll be well on your way to mastering it. Trust me, your future self—and your teammates—will thank you.

Mastering PHPStorm: Essential Shortcuts and Tips for Faster Coding

As a developer, you know that every second counts. PHPStorm, the powerful IDE from JetBrains, is packed with features designed to make coding faster and more efficient—but only if you know how to use them! Here are some essential keybindings and tips that can supercharge your PHPStorm experience and help you code at lightning speed.

Quick Access to Any Action

Ever found yourself lost in PHPStorm’s vast functionality, looking for a specific tool or action? Press Ctrl + Shift + A to bring up the Toggle Actions dialog. This is your command center for quickly finding and triggering any action, even if you don’t know the shortcut for it.

Locate Symbols

Working on a large project? Ctrl + Alt + Shift + N is your friend. This key combination lets you search for any symbol in your project. Whether it's a function, method, or variable, finding it with this shortcut is a breeze.

File Search Made Easy

When you need to open a file but don’t want to dig through directories, use Ctrl + Shift + N. This brings up the file search dialog, allowing you to open any file in your project by typing its name.

Searching for Classes

Quickly locate classes by pressing Ctrl + N. This shortcut is a must for object-oriented projects where multiple classes interact. Simply type the class name, and PHPStorm will locate it for you.

Rename Symbols

Refactoring code often involves renaming variables, functions, or classes. Press Shift + F6 to Refactor/Rename any symbol. This shortcut ensures that PHPStorm updates all references to the renamed symbol, saving you from manually updating each instance.

Replace Text in the Current File

Working on a specific file and need to make some quick replacements? Ctrl + R opens the Find and Replace dialog within the current file, making edits quick and painless.

Project-Wide Search

Need to search or replace text across the entire project? Use Ctrl + Shift + F for a project-wide search. For project-wide find-and-replace, press Ctrl + Shift + R. These shortcuts are invaluable for large-scale code adjustments.

Select the Next Occurrence

Find yourself needing to select multiple occurrences of a word or phrase? Alt + J selects the next occurrence of your current selection (case-sensitive). This feature is ideal for making consistent changes across multiple lines without using traditional search-and-replace.

Move Lines Up or Down

Reordering lines of code is common in refactoring. Alt + Shift + / lets you move the current line (or selection) up or down. A simple, powerful way to reorganize your code with ease.

Get Quick Fixes

If PHPStorm detects an issue or sees a possible improvement, pressing Alt + Enter provides a Quick Fix or Suggestion. It’s a fantastic way to implement suggestions quickly and clean up your code without manually combing through error messages.

Extract Method Shortcut

Refactoring code into methods is essential for clean, reusable code. Highlight the code block and press Ctrl + M + G to Extract Method, instantly creating a new method from the selected code. This is a must for breaking down long, complex functions into manageable pieces.

Bonus: Multi-Cursor Mode

If you’re not using PHPStorm’s multi-cursor mode, you’re missing out on some serious productivity gains! Here’s how to use it:

  1. Select a piece of code.
  2. Press Alt + Shift + Insert to activate multi-cursor mode. Now, you can place multiple cursors wherever needed, allowing you to type or edit in multiple locations simultaneously.

Final Thoughts

Mastering these PHPStorm shortcuts can drastically reduce your time spent on repetitive tasks, allowing you to focus on what really matters: building great software. Give these keybindings a try, and see how they can boost your productivity and help you achieve a smoother, more efficient coding workflow.