Sponsored

Sunday, November 15, 2026

Git troubleshooting: choose the right fix without losing work

Choose a Git command from the change you want to inspect, not from a list of commands to try. Staged edits, unstaged edits, untracked files and committed history are different things. This guide points to focused walkthroughs for each case, with a short diagnostic before you change anything.

Start inside your repository:

git status --short
git diff --stat
git diff --cached --stat

These inspect the current state. They do not clean your working folder, switch branches or rewrite commits. An empty diff is not proof that you have no work: the comparison may simply exclude the changes you are looking for.

A file is staged, but it should not be in the next commit

Use the guide to unstaging a file without losing its edits. This is for a change that should remain on disk while you decide what to commit. It is different from discarding changes or removing a tracked file from future snapshots.

Before running a command, identify the exact path and review its cached diff. Use the path separator -- and quote filenames containing spaces. The walkthrough covers new files and partial staging as well as ordinary tracked edits.

git diff is empty after git add

The default diff compares your working copy with the index. After staging a whole file, those versions can match even though the index differs from your current commit. Read why git diff is empty after git add to choose the right comparison.

Try git diff --cached -- your-file to inspect the staged patch. This does not require staging again or resetting anything. For the full distinction, consult the official diff reference.

A file still appears after adding it to .gitignore

Ignore rules do not make an already tracked file disappear from the index. The tracked-file ignore walkthrough helps distinguish an unmatched pattern from an already tracked path.

Stopping tracking a configuration file changes future commits and can affect collaborators when they pull. It also does not erase an old secret from repository history. If credentials were committed, treat rotation and history cleanup as separate work; an ignore rule is not a security fix.

git stash says there are no local changes

First check whether the files are tracked, untracked or ignored. The untracked-file stash guide explains why a normal stash can omit the work you see in your folder.

Review what would be included before widening a stash operation. Ignored build output and local settings may be large or sensitive. Avoid adding extra flags merely to suppress a confusing message.

You want to remove generated files, but need a preview first

Use the git clean dry-run guide before any deletion. Read the candidate paths and check ignored-file behavior. The preview is an opportunity to stop, not a promise that everything shown is safe to delete.

Untracked files can contain work that Git has never stored. A clean operation is different from unstaging a tracked edit and is not a general repair command.

You need to compare branches without disturbing local work

The branch-comparison walkthrough compares committed snapshots without checking either branch out. It separates an endpoint comparison from a three-dot merge-base comparison.

Choose the question first: do you want the difference between two branch tips, or the changes on one side since a shared base? Local references may be stale; a read-only comparison does not automatically fetch newer remote history.

You need the commit that last changed a line

Use the line-history guide using git blame, then inspect the resulting commit patch. Line attribution is a starting point for investigation, not proof that its author caused a bug.

Whitespace-only changes, renames and local edits can change what you see. The walkthrough shows how to narrow the line range and compare against committed content.

When to stop and inspect further

If short status reports an unresolved conflict, or a command refuses to overwrite a differing staged version, do not force it to match a tutorial. Inspect the index and working copy first. The status output reference explains the columns and conflict states; git restore documents the difference between restoring the index and restoring working files.

Pick the single walkthrough that matches your current state. Keeping a narrow path and reviewing the proposed patch is more useful than running several unrelated cleanup commands.

Saturday, November 14, 2026

Why git status shows a file as both staged and modified

A file can appear under both “Changes to be committed” and “Changes not staged for commit” when you stage one version, then edit it again. Git keeps the staged snapshot in its index. Your later edits remain in the working copy until you stage them too.

Start with these commands, replacing notes.txt with your file:

git status --short
git diff --cached -- notes.txt
git diff -- notes.txt

The second command shows what the next ordinary commit would include for that path. The third shows edits made after its staged snapshot. Neither command changes your file.

Read the two status columns

For an ordinary tracked file outside a merge conflict, short status has two columns before the filename. The first compares the index with the current commit. The second compares your working copy with the index. See the official status output reference for the complete table, including conflict codes.

MM notes.txt

The first M means a modification is staged. The second means the working file also differs from that staged version. It is one path with two comparisons, not two copies competing to be committed. A space in either column matters:

  • M : a modification is staged, with no further working-copy difference for that file.
  • M: the tracked file has an unstaged modification.
  • MM: it has both.
  • AM: a newly added file was staged and then modified again.

See exactly which version Git staged

Consider a committed file containing two lines:

title=old
body=old

You change the first line to title=new, run git add -- notes.txt, then change the second line to body=new. The index still has the new title with the old body. The working copy has both changes.

git show :notes.txt
git diff --cached -- notes.txt
git diff -- notes.txt
git diff HEAD -- notes.txt

In this example, the cached diff contains the title edit; the ordinary diff contains the body edit. The HEAD comparison shows the combined working-copy changes relative to the current commit. These comparison modes are documented in git diff. An ordinary git commit uses the index; do not assume everything currently visible in your editor is staged.

Choose what belongs in the next commit

If the staged version is intentional, leave it staged. Review the cached diff before committing. This is useful when a later edit belongs in a separate change.

If you want the current whole file staged, run:

git add -- notes.txt
git diff --cached -- notes.txt
git status --short

That updates the staged snapshot. If you only want selected later changes, inspect them with git add -p -- notes.txt instead of staging the whole path.

If you want none of this file staged, use Git 2.23 or newer:

git restore --staged -- notes.txt
git status --short
git diff -- notes.txt

With an existing HEAD commit, this restores the index entry from HEAD and leaves the working file alone. Keep --staged: a working-tree restore has a different purpose and can discard edits. The restore reference explains the destination and default source.

What was checked

An isolated Git 2.55.0 Windows fixture verified the MM example, the separate patches, the staged snapshot, restaging, and byte-for-byte preservation after unstaging. It also verified that unstaging a newly added file changes AM to an untracked entry while retaining its contents. These examples assume a repository with an existing commit and no unresolved merge conflict.

For the next step, use the full unstaging walkthrough. If the ordinary diff is unexpectedly empty after staging, see why git diff is empty after git add.

Tuesday, November 10, 2026

How to find which Git commit last changed a line

A retry limit in a configuration file looks wrong. Before editing it, you want to know when it changed and what the commit was trying to fix. Start with git blame for the line, then inspect the commit patch. Both commands let you investigate without switching branches or rewriting history.

Find the commit for one line

Run this from the repository root, replacing the example path with your tracked file. The quotes keep a path containing spaces together:

git blame --date=short -L 2,2 -- "app config.txt"

-L 2,2 selects line 2 only. For lines 10 through 20, use -L 10,20. The separator -- marks the following argument as a file path.

In a small test repository, line 2 was changed from retries=2 to retries=5. The command produced:

da07bf05 (Tutorial Author 2026-11-09 2) retries=5

The first field identifies the commit. The parentheses contain the recorded author, date and line number, followed by the line itself. Your hash and author will differ. Blame identifies the last attributed change to that surviving line; it does not establish who introduced a bug or explain the decision. The Git blame reference describes line ranges and attribution options.

Read the patch before drawing a conclusion

Copy the commit hash from your own result. In the example repository, the next command is:

git show da07bf05 -- "app config.txt"

Replace da07bf05 with your commit hash. The relevant patch in this example contains:

-retries=2
+retries=5

The minus line shows the previous value and the plus line shows the replacement. Read the commit message and surrounding patch too. A timeout change elsewhere in the same commit may explain the retry adjustment. The Git show reference covers viewing commit messages and changes.

Look past a whitespace-only edit

A later formatting commit changed the example to retries = 5. Ordinary blame then pointed to the formatting commit. To compare while ignoring whitespace changes, try:

git blame -w -L 2,2 -- "app config.txt"

In the tested example, this reached the earlier retry-limit commit. Check both patches if spacing can affect your file's meaning. Ignoring whitespace is an investigative option, not a reason to dismiss a change automatically.

Handle a line you edited locally

When the working-copy line was changed to retries = 9 without a commit, blame displayed an all-zero hash and Not Committed Yet. There is no saved commit for that local version. To inspect the committed version instead, specify HEAD:

git blame HEAD -L 2,2 -- "app config.txt"

Line numbers here belong to the committed file. If local edits inserted or removed lines, check that you selected the intended line. These inspections leave the file and staging state alone. If staged edits are confusing the comparison, see why git diff can be empty after git add.

Trace the file's earlier changes

For the history of one file, including earlier names when Git can follow its renames, use:

git log --oneline --follow -- "app config.txt"

This lists commits for the file, not only the selected line. Use its results to inspect older patches. The Git log reference documents the single-file scope of --follow. Blame also follows whole-file renames automatically, while copied or moved blocks can need additional investigation.

Blame cannot annotate a line that has already been deleted from the version you are examining. Inspect an older revision or the file's patches in that case. If the behavior differs between branches, continue with comparing branches without switching. Keep the line attribution, commit explanation and actual behavior as separate pieces of evidence.

Monday, November 9, 2026

Why git stash says no local changes when you have untracked files

You created a new file, ran git stash, and received No local changes to save. The file is still there. If your tracked files are unchanged, an ordinary untracked file can explain that result.

Start by saving open editor buffers. The example below uses a repository with an existing commit, an unchanged tracked.txt, an untracked scratch.txt, and a debug.log ignored by a *.log rule. It was checked with Git 2.55.0 on Windows in a separate test repository.

1. Identify the file category

git status --short --untracked-files=all

In that example, the relevant output is:

?? scratch.txt

The two question marks identify a file outside the index. debug.log is absent from this ordinary status listing because it is ignored. An edited tracked file would have a different status. Review every listed path before deciding what should go into your stash.

The official git status reference describes the status categories. If your question is about an already staged file, use the separate unstaging walkthrough.

2. Include ordinary untracked files deliberately

git stash push -u -m "include scratch notes"

In the test, scratch.txt disappeared from the working directory after this command, while the ignored log stayed in place. The new file had moved into the stash, rather than being committed to the branch.

Review tracked modifications too: adding -u does not restrict the operation to new files. A second check with an edited tracked.txt saved both that edit and scratch.txt. This distinction matters if you intended to set aside only one part of your current work.

3. Inspect the entry before restoring it

git stash list
git stash show --include-untracked --name-only "stash@{0}"

Select the entry with your message in the list. The example uses the newest entry, stash@{0}; substitute the appropriate entry if you have made another stash since then. Including untracked files in the show command made scratch.txt visible in the tested path list.

For a content-level inspection, the stash command also supports patch output. The git stash reference documents the push, show and apply options.

4. Restore, then verify the files

git stash apply "stash@{0}"
git status --short --untracked-files=all

In the clean test state, apply restored the exact bytes of scratch.txt and retained the stash entry. The tracked-and-untracked check also restored both files. Open your files and inspect their contents after applying; an entry in the stash list alone does not verify the result.

If a file with the same name already exists, or the branch has changed, applying can fail or conflict. Read the command's output before trying another operation. Keep the stash entry while resolving and verifying your work.

What about ignored files?

git check-ignore -v -- debug.log

This identifies the matching ignore rule when the path is ignored. The check-ignore documentation explains its verbose output. The tested -u operation left debug.log unchanged; do not assume it saved every file on disk. For tracked-file ignore problems, see why .gitignore does not ignore a tracked file.

The checks above cover ordinary tracked, untracked and ignored files in a repository with a commit. They do not establish conflict recovery, submodule behavior or recovery from losing the repository itself. Keep an independent copy of work you cannot afford to lose.

How to preview git clean without deleting files

Before cleaning a repository, make Git show the candidate paths. The commands in this guide all include -n, so they are previews. Start from the repository root and save any open editor buffers before inspecting the files on disk.

git status --short --untracked-files=all
git clean -nd

A short status listing and a cleanup preview answer different questions. Status helps identify tracked and untracked work. The cleanup preview shows paths selected by the clean command's options. Read both before deciding what should happen next.

A small example you can compare with your own repository

The checks for this guide used Git 2.55.0 on Windows, an existing commit containing tracked.txt, and these ignore rules:

build/
*.log

The working directory also contained notes.txt, draft notes.txt, drafts/todo.txt, build/result.txt and debug.log. Only the first three paths were ordinary untracked work; the build output and log matched the ignore rules.

For that fixture, the ordinary preview produced:

git clean -nd

Would remove draft notes.txt
Would remove drafts/
Would remove notes.txt

Every example file remained present with identical contents afterwards. The tracked file, commit and staged diff were unchanged too. Your output depends on your paths and ignore configuration; it need not match these example lines.

Choose the preview that matches your question

CommandWhat the example selected
git clean -ndOrdinary untracked files and the untracked drafts directory
git clean -ndXIgnored build output and debug.log only
git clean -ndxBoth groups of untracked paths, including ignored ones

The capital X and lowercase x are different options. In the tests, the capital-X preview listed build/ and debug.log but left out notes.txt. The lowercase-x preview listed all five untracked paths or directories. None of these commands changed their bytes.

The official git clean reference defines the dry-run, directory and ignore-selection options. Keep -n in place while comparing the candidate lists. Including -d makes ordinary untracked directories part of the preview.

Restrict the preview to a named path

git clean -nd -- "draft notes.txt"

The double hyphen separates options from the path. Quotes keep the filename with spaces together in PowerShell and common Unix shells. In the isolated check, the result named draft notes.txt without selecting the other example paths. That file's bytes were unchanged afterwards.

Use your own path, then read the entire result. A preview is an observation of the current working directory; creating another file or changing ignore rules can change a later result.

Explain a surprising omission

git check-ignore -v -- build/result.txt debug.log

The test output identified the build/ and *.log rules in .gitignore. The verbose check-ignore reference explains the rule and pathname fields. Ignore behavior can also come from other configured ignore sources, so inspect the reported rule rather than assuming it must be in the repository file.

A tracked file is a different case. Use git status to identify its state, and see the tracked-file ignore walkthrough when changing .gitignore has no effect. If your goal is to remove something from the next commit, unstage it while retaining your edits instead.

This guide stops at inspection. Untracked files may have no committed copy for Git to recover. Keep an independent copy of anything important before moving beyond a preview. The tests cover ordinary files and directories, not nested repositories, submodules or recovery after deletion.

Sunday, November 8, 2026

How to compare two Git branches without switching branches

To compare the committed contents of two Git branches, give both names to git diff:

git diff main feature/login --

You can run this while staying on your current branch. The comparison uses the commits named by main and feature/login, rather than your current working files. The git diff reference documents this two-commit form.

Check which branches you are comparing

git status --short
git branch --show-current
git branch --list main feature/login

Replace the example names with branches that exist in your repository. The branch listing lets you check the names before running the comparison. As the git branch documentation explains, --show-current prints your current branch; it prints nothing when HEAD is detached.

A dirty working tree does not require a branch switch for this comparison. Keep the initial status output as a record of any staged, unstaged or untracked work. The status reference describes those separate categories.

Compare the two branch tips

Start with a summary, then inspect the patch for a particular path:

git diff --stat main feature/login --
git diff main feature/login -- settings.txt

Here, main is the before side and feature/login is the after side. Minus lines belong to the first snapshot; plus lines belong to the second. The two-dot spelling, git diff main..feature/login --, makes the same endpoint comparison.

Consider this small history. A is the shared starting commit. B adds a line to README.md on main. C changes color=blue to color=green in settings.txt on feature/login.

      B  main
     /
A---+
     \
      C  feature/login

In the verified practice repository, this command listed two paths:

git diff --name-only main feature/login --

README.md
settings.txt

README.md appears because B and C contain different versions of it: C does not contain B's added line. That output does not mean the feature commit edited both files. The command is comparing snapshots, not listing commits.

Show the feature side since the shared ancestor

For the changes between the shared starting point and the feature tip, use three dots:

git diff --name-only main...feature/login --

settings.txt

In this example, that compares A with C, leaving out B's later README edit. You can inspect the common ancestor with:

git merge-base main feature/login

The merge-base reference explains how Git finds a shared ancestor. The history here has one merge base; more complicated histories can have several.

Argument order matters. In this same repository, git diff --name-only feature/login...main -- lists README.md because the comparison now follows A to B. Three dots are not simply a shorter way to request the endpoint diff.

What happened to the uncommitted work?

The command checks used a staged red version of settings.txt, an unstaged purple version, and an untracked scratch.txt. The committed branch comparison still showed blue changing to green. After all comparisons, the current branch, HEAD, index contents and both local files matched their initial state.

That result is specific to the branch-to-branch commands above. Plain git diff examines a different comparison. If you need to change what is staged, the guide to unstaging a file while keeping its edits covers that operation separately.

These commands inspect references already present locally. They do not contact a remote server or guarantee that a branch name reflects its latest remote state. If a name is missing, check the repository and available branches before trying a different command.

Saturday, November 7, 2026

Why .gitignore does not ignore a tracked file

You added a filename to .gitignore, saved the file, and Git still reports changes to it. The first question is whether Git already tracks that path. Ignore rules are intended for untracked files; they do not remove an existing file from the index. The gitignore reference explains that distinction.

This example uses settings.local.json in a repository that already has a commit. Save open editor buffers and keep a backup of any valuable local settings before changing tracking. Check the repository root and use your actual filename in each command.

1. Check whether the file is tracked

git status --short
git ls-files --error-unmatch -- settings.local.json

If the second command prints settings.local.json, the path is in the index. If it exits with an error, check the spelling and repository location; the file may already be untracked. The git ls-files documentation defines this index check. Do not assume that every file visible in your editor is tracked.

2. Check the ignore rule separately

For a file at the repository root, add this line to the root .gitignore:

/settings.local.json

Then inspect the matching rule:

git check-ignore -v --no-index -- settings.local.json

The verbose output identifies the ignore file, line number and matching pattern. The --no-index option lets this diagnostic examine a path even when it is tracked. Without it, tracked paths are normally omitted. See git check-ignore.

3. Remove only that path from tracking

First preview the operation, then perform it if the path is correct:

git rm -n --cached -- settings.local.json
git rm --cached -- settings.local.json

The first command is a dry run. The second removes the path from the index while leaving the working file on disk. Keep --cached in the command. If Git refuses because the staged content differs, inspect those versions rather than adding --force. The git rm reference covers the option and its checks.

4. Review the staged change before committing

git add -- .gitignore
git status --short
git diff --cached --stat

A staged deletion for settings.local.json is expected: the next commit will omit that path. Confirm the local file still opens and contains the settings you need. Review the complete staged changes before making your normal commit.

In the isolated verification for this example, the local file stayed byte-for-byte unchanged after cached removal and after the commit. An older commit still contained it. A clean collaborator clone lost the tracked file when it pulled the removal commit. Discuss that effect with your team if everyone needs a local configuration file; a separate example configuration can document the required fields.

If you only meant to unstage an edit

Stopping tracking changes future commits. If the file should remain tracked and you only want to remove an edit from the next commit, follow the guide to unstaging a file without losing its current edits instead. Choose the operation based on what the next commit should contain.

Friday, November 6, 2026

Why git diff is empty after git add

You edited a file, staged it, and ran git diff. Nothing appeared. Before trying an undo command, check the comparison: plain git diff compares the working file with the index. After staging all its changes, those two copies can match.

The change can still be staged for your next commit. Use git diff --cached to inspect that comparison. The official git diff reference describes the different forms.

Three versions of one file

For an ordinary tracked file in a repository with an existing commit, keep these three versions in mind:

  • HEAD: the version in the current commit.
  • The index: the version prepared for the next commit.
  • The working file: the saved contents on disk.

Run this inspection sequence from the repository root:

git status --short
git diff -- app.txt
git diff --cached -- app.txt
git diff HEAD -- app.txt

The commands answer, respectively: what is the path's status, what differs between disk and index, what differs between index and HEAD, and what differs between disk and HEAD. They inspect content without editing it.

A small example you can follow

Use a practice repository where app.txt was committed with one line, color=blue. In your editor, change that line to color=green and save it. Plain git diff should show the color change; the cached comparison should be empty if nothing else was staged for this file.

Now stage that path:

git add -- app.txt
git diff -- app.txt
git diff --cached -- app.txt

Plain diff is now empty, but the cached diff still shows the color change. Staging copied the saved contents into the index; it did not create a commit. The git add documentation explains how staging records file contents.

What if you edit the file again?

After staging the green version, add a second line, theme=dark, and save without staging again. The plain diff now shows the extra theme line. The cached diff still shows the earlier color change, and a comparison with HEAD shows both saved changes.

Short status can show MM for this case. In the ordinary tracked-file case, its first column describes the index and its second describes the working tree. A staged-only modification has M in the first column; an unstaged-only modification has M in the second. See the git status reference for other states, including conflicts.

New and ignored files need another check

git status --short --untracked-files=all
git status --short --ignored -- build.log

An untracked file can contain useful work even when plain diff shows nothing; short status marks it with two question marks. An ignored path can appear with two exclamation marks when ignored files are requested. Open the relevant file and check its tracking state before deciding what to stage.

Review the proposed commit

Before committing, read git diff --cached without a path filter to review everything currently staged. If a tracked file belongs in a later commit, the unstaging tutorial shows how to remove it from that selection while preserving its current saved contents.

Thursday, November 5, 2026

Docker for Beginners: Run Your First Container and Understand the Commands


DevOps
· By Kashmitha Madushan · 4 November 2026

Docker is easier to learn when you stop treating it as a collection of mysterious commands. Start with one image, run a container, inspect it, and delete it. Those four actions explain much of the workflow you will use later with ASP.NET Core or other applications.

What is an image, and what is a container?

An image is a packaged template containing the software and instructions needed to run an application. A container is a running or stopped instance of an image. You can create multiple containers from the same image without copying your entire project by hand.

1. Install Docker Desktop or Docker Engine

Follow Docker's official installation guide for your operating system. On Windows, verify the WSL 2 requirements and ensure virtualization is enabled. After installation, open a terminal and run:

docker --version
docker info

The first command displays client information. The second checks whether Docker can communicate with its engine.

2. Run a container

docker run --name demo-nginx -d -p 8080:80 nginx:stable

This starts an Nginx web server in the background. The mapping 8080:80 forwards port 8080 on your machine to port 80 in the container. Visit http://localhost:8080 in your browser.

3. Inspect and stop it

docker ps
docker logs demo-nginx
docker stop demo-nginx
docker ps -a
docker rm demo-nginx

docker ps lists running containers. docker logs helps when startup fails. Stopping a container does not remove it; that is why the cleanup command is separate.

4. Where does a Dockerfile fit?

A Dockerfile tells Docker how to build an image from your own application. When you reach that stage, learn FROM, WORKDIR, COPY, RUN and CMD. Don't confuse building an image with starting a container.

Common problems

If the command says it cannot connect to the Docker daemon, check that Docker Desktop or the engine is running. If port 8080 is already in use, pick a different available host port. If image downloads fail, verify network access and any corporate proxy settings.

Practice idea: run two Nginx containers on different host ports, then stop and remove both. That one exercise builds confidence quickly.

Further reading: Official reference documentation.

Kashmitha Madushan writes about development, DevOps, Unity and practical software workflows. Examples are educational drafts; check the steps in your own environment before relying on them.

Wednesday, November 4, 2026

How to unstage a file in Git without losing your changes

You have edited a file, run git add, and noticed it belongs in a later commit. Before changing anything, save open editor buffers: Git operates on the files on disk.

This walkthrough uses a repository with an existing commit and an ordinary tracked file named notes.txt. It does not cover merge conflicts. Replace the example path with your own and run the commands from the repository root.

1. Inspect what is staged

git status --short
git diff --cached -- notes.txt
git diff -- notes.txt

The two diffs answer different questions. The cached diff shows the proposed commit relative to HEAD. The plain diff compares the working copy with the index. A file can therefore appear in both comparisons if you edited it again after staging. See the official git diff reference.

2. Unstage just the intended file

git restore --staged -- notes.txt

With --staged, restore targets the index and uses HEAD by default. The current working file is left in place. The separator before the path makes the command easier to read when substituting filenames. For a path containing spaces, quote it:

git restore --staged -- "draft notes.txt"

This command requires an existing HEAD commit. If Git reports that HEAD cannot be resolved, stop: a brand-new repository before its first commit needs a different workflow. Do not remove --staged as a workaround. Restore without that option targets working files and can discard edits. These distinctions are described in the git restore documentation.

3. Confirm the result

git status --short
git diff --cached -- notes.txt
git diff -- notes.txt

For the simple tracked-file example, status changes from M in the first column to M in the second column. The first column describes the index; the second describes the working tree. After unstaging, the cached diff for this path should be empty, while the plain diff should show the saved edits. Other staged files remain candidates for your next commit. The git status reference explains the columns and special cases.

New files and partially staged edits

A newly added file that is absent from HEAD becomes untracked after unstaging; status shows two question marks. Its contents remain on disk, but ordinary git diff does not display untracked file contents. Open the file to inspect it.

For a partially staged file, unstaging preserves the latest disk contents but removes the earlier staging selection for that path. Review the file again before using git add; do not assume that the old selection is saved separately.

Before your next commit

Read the staged diff for the whole repository before committing. Confirm that only the intended paths and changes remain. Unstaging is useful for correcting commit contents; it is not a backup. Keep valuable work saved, and use your normal backup process.

10 VS Code Extensions Worth Considering for C# and Web Development


Programming
· By Kashmitha Madushan · 4 November 2026

Extensions make VS Code more comfortable, but installing everything in the marketplace is a quick way to end up with a cluttered editor. A smaller set is easier to understand, update and troubleshoot. Here are ten extensions or extension categories worth evaluating if you work with C#, React, HTML and APIs.

Start with your language support

  1. C# Dev Kit: Microsoft's tooling for C# development. Check its prerequisites and licensing before using it at work.
  2. C#: Microsoft's language extension provides language services that support many C# workflows.
  3. ESLint: surfaces lint findings in JavaScript and React code when your project has ESLint configured.
  4. Prettier: formats supported files consistently; decide whether it or another formatter owns each language.
  5. EditorConfig: applies repository-level indentation and whitespace conventions.

Tools that improve daily navigation

  1. GitLens: explores Git history and blame information without repeatedly switching to a terminal.
  2. REST Client: lets you keep simple HTTP requests in text files, useful for quick API experiments.
  3. SQLTools: offers database connections and query tooling; add only the driver you actually need.
  4. Docker: provides container-related editing and exploration when your project uses containers.
  5. GitHub Actions: assists with workflow files and helps make CI configuration easier to navigate.

My suggested minimal installation

For a beginner C# Web API project, start with C# support, EditorConfig, and one formatter. Add ESLint if you have a React frontend. Only install Docker and GitHub Actions extensions after your repository starts using those tools.

How to judge whether an extension is useful

Open Extensions with Ctrl+Shift+X, verify the publisher, review recent updates, and read the extension's permission and setup requirements. Try it in a single project before making it part of every workspace. If the editor suddenly slows down, temporarily disable recently installed extensions and compare.

A mistake to avoid

Don't enable multiple competing formatters for the same file type and then wonder why code changes after each save. Commit a shared .editorconfig and document your team's formatter choice.

Bottom line: a purposeful extension list beats a large collection of plugins you never use.

Further reading: Official reference documentation.

Kashmitha Madushan writes about development, DevOps, Unity and practical software workflows. Examples are educational drafts; check the steps in your own environment before relying on them.

A Developer's Guide to Safe Git Rebase and Merge Workflows

By Kashmitha Madushan · Prepared 4 November 2026.

If Git shows a non-fast-forward rejection, your local branch is behind the remote branch, or the histories have diverged. Do not force-push until you unde
rstand what changed.

1. Check your current branch and changes

git status
git branch --show-current
git remote -v

If you have uncommitted work, commit it or stash it before rebasing. Read the actual branch names in your repository rather than copying main blindly.

2. Download the latest remote information

git fetch origin
git log --oneline --graph --decorate --all -15

Inspect commits to determine whether your local branch and the remote have diverged.

3. Rebase your commits onto the latest remote branch

git pull --rebase origin main

Replace main with your actual target branch. If conflicts occur, open and resolve the affected files, then run:

git add path/to/resolved-file
git rebase --continue

If you must stop the rebase, use git rebase --abort. Once you have checked the final result, push:

git push origin main

Merge instead of rebase?

Teams sometimes prefer merge commits. Follow your repository's branching policy rather than rewriting shared history. A force push can overwrite other people's work, so avoid it for this situation unless your team has explicitly approved a safe recovery process.

Before you finish

Run your tests, check the diff, and verify that the remote branch contains the intended changes. See the official git pull documentation.

Written by Kashmitha Madushan, Associate DevOps Engineer and full-stack developer. Software versions and tools can change; check the linked official documentation before applying steps to a production system.

How to Configure CORS for a React and ASP.NET Core Application


By Kashmitha Madushan · Prepared 4 November 2026.

When a React app calls an ASP.NET Core API on a different origin, the browser may block the request unless the API returns the correct cross-origin headers. A CORS failure is generally fixed on the server, not by disabling browser security.

Example development setup

Assume React is running at http://localhost:5173 and your API uses a different origin. Replace the addresses in this guide with your actual local addresses.

Configure an explicit origin in Program.cs

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddControllers();
builder.Services.AddCors(options =>
{
    options.AddPolicy("ReactDev", policy =>
        policy.WithOrigins("http://localhost:5173")
              .AllowAnyHeader()
              .AllowAnyMethod());
});

var app = builder.Build();
app.UseHttpsRedirection();
app.UseRouting();
app.UseCors("ReactDev");
app.UseAuthorization();
app.MapControllers();
app.Run();

Keep CORS middleware in the correct position in your request pipeline. Your actual application might also use authentication, custom middleware, or endpoint-specific policies.

Common mistakes

  • Using the wrong frontend port or scheme.
  • Adding CORS settings only in React.
  • Using wildcard origins with credentials; this combination is not allowed.
  • Confusing a backend 401/403/500 response with a CORS configuration problem.

Debugging checklist

Open browser developer tools, select Network, inspect the OPTIONS preflight where present, and check the API response and console error. Test a known-good endpoint before expanding the policy.

Official reference: ASP.NET Core CORS documentation. Verify the sample against your target .NET version before publishing.

Written by Kashmitha Madushan, Associate DevOps Engineer and full-stack developer. Software versions and tools can change; check the linked official documentation before applying steps to a production system.

A Developer's Guide to Publishing Frontend Projects on GitHub Pages


By Kashmitha Madushan · Prepared 4 November 2026.

GitHub Pages is a convenient option for static frontend projects. It does not run a .NET server or host a database-backed API, so deploy your ASP.NET Core backend separately if you need one.

1. Prepare your project

Make sure your React application builds successfully. A typical Vite project uses:

npm install
npm run build

Review the generated dist directory. If deploying to a project repository at a subpath, configure Vite's base setting to match that path.

2. Create a repository

Push your source files to a GitHub repository. Never commit passwords or private API keys.

3. Choose your deployment method

In the repository settings, open Pages. GitHub Pages supports publishing from a branch or through GitHub Actions. A React/Vite build commonly uses a GitHub Actions workflow to build and deploy the generated static files.

4. Test routing and assets

Open your published site on mobile and desktop. Check images, CSS, links, and direct navigation to routes. Client-side routes may need a static-host-compatible fallback strategy.

Limitations

Use a separate API host for ASP.NET Core. Never store secrets in frontend environment variables that are bundled into public client-side files.

Read the current official guides: GitHub Pages and Vite static deployment.

Written by Kashmitha Madushan, Associate DevOps Engineer and full-stack developer. Software versions and tools can change; check the linked official documentation before applying steps to a production system.

How to Use AI Assistants for SQL Queries Safely and Effectively

By Kashmitha Madushan · Prepared 4 November 2026.

AI assistants can help you learn SQL faster, but they can also invent column names, misunderstand joins, or suggest expensive queries. Use them as explainers, not as substitutes for examining your database schema and testing queries.

1. Start with a tiny example

SELECT c.Name, COUNT(o.Id) AS OrderCount
FROM Customers c
LEFT JOIN Orders o ON o.CustomerId = c.Id
GROUP BY c.Name;

This example groups orders by customer name. In a real database, different customers may share the same name, so grouping by a unique customer ID is safer.

2. Ask for a line-by-line explanation

Explain this SQL query for a beginner. Describe the JOIN, grouping, and what happens to customers with no orders. Identify assumptions and possible bugs. Do not invent schema details.

3. Verify the explanation

Compare the result to a small test dataset. Check row counts, NULL behavior, join cardinality, and whether indexes are relevant to performance.

4. Protect sensitive information

Never paste production credentials or personally identifying database records into an AI service. Use synthetic examples and review the service's data-handling terms.

5. Test before deploying

Check the execution plan and run changes in a safe environment. For data-modifying statements, use transactions where appropriate and keep reliable backups.

Related reading: Microsoft SQL SELECT documentation.

Written by Kashmitha Madushan, Associate DevOps Engineer and full-stack developer. Software versions and tools can change; check the linked official documentation before applying steps to a production system.

How to Safely Free Up Disk Space on Windows Without Extra Tools

By Kashmitha Madushan · Prepared 4 November 2026.

If your Windows laptop is running out of disk space, begin with built-in storage tools instead of downloading an unfamiliar cleaner. Always confirm what a deletion option removes.

1. Find what consumes storage

Open Settings → System → Storage and inspect categories such as installed applications, temporary files, and documents. Exact menu wording varies by Windows version.

2. Review temporary files

Select the temporary files category and inspect the listed items before deleting anything. Pay particular attention to Downloads and Recycle Bin content: you may still need those files.

3. Uninstall unused applications

Open Installed apps, sort by size if available, and uninstall only software you recognize and no longer use. Avoid deleting application folders manually.

4. Move large personal files

Consider moving videos, project archives, or old installers to a trusted external drive or cloud storage. Verify the copy opens correctly before deleting the source.

5. Check Storage Sense

Windows Storage Sense can help manage temporary files. Review its schedule and deletion rules before enabling automatic cleanup.

What not to delete

Do not remove random files from Windows, Program Files, or application-data directories based on an unknown online tutorial. If you're unsure, search official documentation first.

Official reference: Microsoft: Free up drive space in Windows.

Written by Kashmitha Madushan, Associate DevOps Engineer and full-stack developer. Software versions and tools can change; check the linked official documentation before applying steps to a production system.

A Practical Framework for Testing and Benchmarking Free AI Plans

By Kashmitha Madushan · Prepared 4 November 2026.

Free AI plans can look similar until you reach a message limit, try to export a file, or discover that a feature requires payment. Evaluate tools around your real workflow rather than a dramatic top-ten ranking.

Define the job first

Is the tool supposed to summarize documents, explain code, improve writing, or brainstorm project ideas? One tool may be great for one use case and poor for another.

Test the same inputs

Create three non-sensitive prompts: a straightforward request, a difficult edge case, and a request that requires verifiable sources. Compare how each tool performs without changing your success criteria midway.

Check these factors

  • Accuracy and ability to acknowledge uncertainty.
  • Availability and limits of the free tier.
  • Data privacy controls and terms.
  • Export options and accessible formats.
  • Ease of use on mobile and desktop.
  • Whether citations actually support the output.

Record your findings

Use a spreadsheet with columns for tool, task, pass/fail, notes, free-plan restrictions, and date tested. Do not publish a claim like “unlimited” without checking the official product terms.

Why this method is useful

A tested, well-documented comparison helps readers choose the right tool and gives you more original value than copying a marketing feature list. Add your own results only after you have actually tested each product.

Written by Kashmitha Madushan, Associate DevOps Engineer and full-stack developer. Software versions and tools can change; check the linked official documentation before applying steps to a production system.

Practical developer tutorials, AI tool comparisons, troubleshooting guides and free software resources.

Search This Blog

Powered by Blogger.

Blog Archive

Git troubleshooting: choose the right fix without losing work

Choose a Git command from the change you want to inspect, not from a list of commands to try. Staged edits, unstaged edits, untracked files ...