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!

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!

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.

Installing and Configuring Elasticsearch and Kibana on Ubuntu

I've always wanted to write this article but never got the chance to do so, I had written some notes on how to set up Elasticsearch and Kibana on an Ubuntu server (20.04 or later). Whether you're building a search engine, analyzing logs, or just exploring the Elastic Stack, this guide will help you get everything up and running smoothly.

Here's how I did it:

Setting up Elasticsearch

Add the Elasticsearch GPG key and repository

curl -fsSL https://artifacts.elastic.co/GPG-KEY-elasticsearch | sudo gpg --dearmor -o /usr/share/keyrings/elastic.gpg
echo "deb [signed-by=/usr/share/keyrings/elastic.gpg] https://artifacts.elastic.co/packages/7.x/apt stable main" | sudo tee -a /etc/apt/sources.list.d/elastic-7.x.list

Install Elasticsearch

sudo apt update
sudo apt install elasticsearch

Configure Elasticsearch by editing /etc/elasticsearch/elasticsearch.yml

network.host: localhost
http.port: 9200
http.host: 0.0.0.0

Start and enable Elasticsearch

sudo systemctl start elasticsearch
sudo systemctl enable elasticsearch

Set up an NGINX reverse proxy for Elasticsearch

Add this server block to your NGINX config (e.g., /etc/nginx/sites-available/your_domain):

server {
   listen 8834;

   # Uncomment for SSL
   # listen 8834 ssl;
   # ssl_certificate /path/to/certificate/crt.pem;
   # ssl_certificate_key /path/to/key/key.pem;
   # ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
   # ssl_prefer_server_ciphers on;
   # ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

   server_name your_domain;

   location / {
      proxy_pass http://localhost:9200;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_cache_bypass $http_upgrade;
   }
}

and then test and restart NGINX service:

sudo nginx -t
sudo systemctl restart nginx

Once done, you can verify if Elasticsearch is running by visiting http://yourdomain.com:8834 in your browser. You should see a JSON response with Elasticsearch details.

Setting up Kibana

Install Kibana

sudo apt install kibana

Configure Kibana by editing /etc/kibana/kibana.yml

server.port: 5601
server.host: 0.0.0.0
elasticsearch.hosts: ["http://localhost:9200"]

Start and enable Kibana

sudo systemctl enable kibana
sudo systemctl start kibana

Create an admin user for Kibana

echo "your_admin_username:`openssl passwd -apr1`" | sudo tee -a /etc/nginx/htpasswd.users

Make sure that you enter a strong password when prompted.

Set up an NGINX reverse proxy for Kibana

Add this server block to your NGINX config:

server {
   listen 8833;

   # Uncomment for SSL
   # listen 8833 ssl;
   # ssl_certificate /path/to/certificate/crt.pem;
   # ssl_certificate_key /path/to/key/key.pem;
   # ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
   # ssl_prefer_server_ciphers on;
   # ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';

   server_name your_domain;

   auth_basic "Restricted Access";
   auth_basic_user_file /etc/nginx/htpasswd.users;

   location / {
      proxy_pass http://localhost:5601;
      proxy_http_version 1.1;
      proxy_set_header Upgrade $http_upgrade;
      proxy_set_header Connection 'upgrade';
      proxy_set_header Host $host;
      proxy_cache_bypass $http_upgrade;
   }
}

and then test and restart NGINX service:

sudo nginx -t
sudo systemctl restart nginx

Once done, you can try to access Kibana by visiting http://yourdomain.com:8833. You'll be prompted for the admin credentials you created earlier.

Wrapping Up

And there you go! Elasticsearch and Kibana are now up and running on your Ubuntu server, ready to help you search, analyze, and visualize your data. Whether you're diving into logs, building a search feature, or just experimenting with the Elastic Stack, this setup should give you a solid foundation.

References

Hope you found this useful!

How to Send Test Emails via PowerShell?

How to Send Test Emails via PowerShell

Whenever I wanted to send a test mail from a Windows Server, I make use of PowerShell. This makes it easier and is a quick yet efficient way to test email functionality, troubleshoot SMTP servers, or verify email delivery.

Here’s what I usually do, including examples with and without user authentication.

1. Basic Command to Send a Test Email

The Send-MailMessage cmdlet in PowerShell makes it easy to send emails via an SMTP server. Here’s the basic command I used:

Send-MailMessage -SmtpServer "0.0.0.0" -Port 25 -From "sample@example.com" -To "john.doe@example.com" -Subject "A subject" -Body "A body"
  • -SmtpServer: The IP address or hostname of the SMTP server.
  • -Port: The SMTP port (default is 25).
  • -From: The sender’s email address.
  • -To: The recipient’s email address.
  • -Subject: The subject of the email.
  • -Body: The content of the email.

This command works for SMTP servers that don’t require authentication (e.g., internal SMTP relays).

2. Sending Emails with User Authentication

If the SMTP server requires authentication, you can add the -Credential parameter to provide a username and password. Here’s how:

$credential = Get-Credential
Send-MailMessage -SmtpServer "smtp.example.com" -Port 587 -From "sample@example.com" -To "john.doe@example.com" -Subject "A subject" -Body "A body" -Credential $credential -UseSsl
  • -Credential: Prompts for a username and password. You can also create a PSCredential object programmatically.
  • -UseSsl: Enables SSL/TLS encryption, which is often required for authenticated SMTP servers (e.g., port 587).

Example with Hardcoded Credentials:

If you don’t want to be prompted for credentials, you can create a PSCredential object like this on PowerShell ISE:

$username = "sample@example.com"
$password = ConvertTo-SecureString "YourPassword" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($username, $password)

Send-MailMessage -SmtpServer "smtp.example.com" -Port 587 -From "sample@example.com" -To "john.doe@example.com" -Subject "A subject" -Body "A body" -Credential $credential -UseSsl

3. Adding Attachments

You can also attach files to your email using the -Attachments parameter:

Send-MailMessage -SmtpServer "smtp.example.com" -Port 587 -From "sample@example.com" -To "john.doe@example.com" -Subject "A subject" -Body "A body" -Attachments "C:\path\to\file.txt" -Credential $credential -UseSsl

4. Troubleshooting Tips

Connection Issues:

If the email fails to send, ensure the SMTP server is reachable and the port is open. Use Test-NetConnection to verify connectivity:

Test-NetConnection -ComputerName smtp.example.com -Port 587

Authentication Errors:

Double-check the username and password. If the SMTP server requires a specific authentication method (e.g., OAuth), you may need additional configuration.

SSL/TLS Errors:

Ensure the -UseSsl parameter is used if the SMTP server requires encryption.

Example Workflow:

Here’s a complete example with authentication and attachments:

# Create credentials
$username = "sample@example.com"
$password = ConvertTo-SecureString "YourPassword" -AsPlainText -Force
$credential = New-Object System.Management.Automation.PSCredential ($username, $password)

# Send email with attachment
Send-MailMessage -SmtpServer "smtp.example.com" -Port 587 -From "sample@example.com" -To "john.doe@example.com" -Subject "Test Email with Attachment" -Body "Please find the attached file." -Attachments "C:\path\to\file.txt" -Credential $credential -UseSsl

Why do this way?

Using PowerShell to send test emails is a powerful way to:

  • Test SMTP server configurations.
  • Verify email delivery and troubleshoot issues.
  • Automate email notifications in scripts.

Whether you’re working with an internal SMTP relay or an external server requiring authentication, PowerShell’s Send-MailMessage cmdlet makes it easy to get the job done.

Hope you found this useful!

How to Find Users with Duplicate Email Addresses in SQL?

When managing a database with user information, ensuring data integrity is crucial. One common issue that can arise is duplicate email addresses in the users table.

Let me show you how to write a simple yet powerful SQL query to identify such duplicates!

The Problem

In many applications, email addresses should be unique identifiers for users. However, duplicates can sneak into the database due to bugs, manual data imports, or other anomalies. Detecting and resolving these duplicates is essential to maintain data integrity and ensure proper functionality of user-related features, such as authentication.

The Solution

Using SQL, you can quickly find all duplicate email addresses in your users table by leveraging the GROUP BY and HAVING clauses.

Here’s the query:

SELECT email, COUNT(*) AS email_count
FROM users
GROUP BY email
HAVING COUNT(*) > 1;

How It Works:

  1. GROUP BY email: Groups the rows in the users table by the email column, so each group represents a unique email.
  2. COUNT(*): Counts the number of rows in each group.
  3. HAVING COUNT(*) > 1: Filters the groups to only include those where the count is greater than 1, i.e., duplicate email addresses.

Enhanced Query for User Details

If you want to see more details about the users who share the same email address (e.g., user IDs, names), you can use a subquery:

SELECT u.*
FROM users u
JOIN (
    SELECT email
    FROM users
    GROUP BY email
    HAVING COUNT(*) > 1
) dup_emails ON u.email = dup_emails.email;

Explanation

  • The subquery identifies all duplicate email addresses.
  • The main query joins this result with the users table to retrieve detailed information about each user associated with the duplicate emails.

Final Thoughts

This simple query can save you a lot of time when auditing your database for duplicate entries. Whether you’re cleaning up data or debugging an issue, identifying duplicates is an important step toward ensuring a robust and reliable application.

Hope you found this tip useful!