Opens in a new tab

Git & GitHub

Git and GitHub are a core part of how I manage source code, develop software safely and keep projects maintainable over time.

I use Git for version control and GitHub as a collaboration, repository and automation platform. Together, they give me a structured way to track changes, experiment without damaging stable code, review development history and maintain reliable releases.

For me, version control is not simply a place to store source files. It is part of the engineering process.

How I use Git & GitHub

I use Git and GitHub for:

  • source-code version control,
  • feature development,
  • bug fixing,
  • release management,
  • branching and merging,
  • reviewing historical changes,
  • maintaining multiple project versions,
  • collaboration,
  • issue tracking,
  • documentation,
  • automated builds and tests,
  • deployment workflows,
  • backups of development history.

This applies to web development, Android applications, backend projects, utilities and experimental software.

Version Control as a Safety Layer

Software changes constantly.

New features, dependency updates and bug fixes can introduce unexpected problems even when the original change appears small.

Git gives me a complete history of those changes.

If something goes wrong, I can identify:

  • what changed,
  • when it changed,
  • why it changed,
  • which files were affected,
  • which earlier state was known to work.

This makes development significantly safer than editing a single uncontrolled copy of a project.

Meaningful Commits

I prefer commits that represent understandable development steps.

A useful commit should make it reasonably clear what changed and why.

This improves:

  • debugging,
  • code review,
  • project history,
  • future maintenance.

When investigating a regression months later, a meaningful history is much more useful than a sequence of vague commits such as “update” or “fix”.

I therefore treat commit history as technical documentation.

Branching

Branches allow me to develop changes without immediately modifying the stable version of a project.

I use branches for work such as:

  • new features,
  • experimental changes,
  • refactoring,
  • bug fixes,
  • larger architectural changes.

This makes it possible to test a change independently before deciding whether it belongs in the main codebase.

For larger projects, this separation becomes increasingly important because several pieces of work may be in progress at the same time.

Merging and Conflict Resolution

Parallel development sometimes results in conflicts.

I resolve Git conflicts by understanding the actual code changes rather than blindly selecting one side.

A conflict often means that two changes affect the same part of the system, so the correct result may require combining both intentions.

This is particularly important in configuration files, application architecture and frequently modified components.

Stable Main Branches

I prefer keeping the primary branch in a usable state.

Experimental work belongs in separate branches until it is sufficiently tested and ready to become part of the main project.

This reduces the chance that unfinished work will unexpectedly become part of a release.

For production software, the repository should make it clear which code represents the current stable state.

Tags and Releases

For projects with identifiable versions, I use tags and releases to preserve important milestones.

This can include versions such as:

  • 1.0.0,
  • 1.1.0,
  • 2.0.0.

A release should correspond to a known state of the source code.

This makes it possible to reproduce older builds, investigate historical problems and understand exactly which code was delivered at a particular point in time.

Semantic Versioning

Where appropriate, I use structured version numbers to communicate the scale of changes between releases.

A typical version may distinguish between:

  • major changes,
  • new backward-compatible functionality,
  • bug fixes.

The exact release strategy depends on the project, but predictable versioning makes software easier to manage for both developers and users.

GitHub Repositories

GitHub provides the central location for many of my development projects.

A repository can contain more than source code.

I use repositories to organize:

  • code,
  • documentation,
  • configuration,
  • release information,
  • development notes,
  • issues,
  • automation workflows.

This keeps the technical history of a project connected to the project itself.

Public and Private Repositories

Not every repository should be public.

I choose repository visibility based on the project.

Public repositories are useful for:

  • open-source software,
  • examples,
  • reusable tools,
  • technical demonstrations.

Private repositories are appropriate for:

  • client work,
  • proprietary applications,
  • credentials-sensitive infrastructure,
  • internal development.

Version control remains valuable regardless of whether the code is publicly visible.

GitHub Issues

For projects that need structured task and bug tracking, I use GitHub Issues to document work that needs attention.

An issue can describe:

  • a bug,
  • a requested feature,
  • a technical problem,
  • an improvement,
  • future work.

Keeping this information attached to the repository makes it easier to connect development decisions with the code that eventually implements them.

Pull Requests

Pull requests provide a useful review boundary before changes enter a stable branch.

Even when working independently, the pull-request model can be useful for larger changes because it provides a clear overview of:

  • changed files,
  • commits,
  • code differences,
  • discussion,
  • automated checks.

For collaborative projects, pull requests also create a structured environment for reviewing contributions before merging them.

Code Review

Code review is not only about finding syntax errors.

A useful review considers:

  • correctness,
  • maintainability,
  • security,
  • architecture,
  • unnecessary complexity,
  • edge cases,
  • compatibility.

GitHub’s comparison tools make it easier to inspect exactly what a proposed change modifies.

This is especially valuable for large patches where understanding the difference is more useful than rereading entire files.

GitHub Actions

GitHub Actions can automate development tasks whenever repository events occur.

I use or design automated workflows for tasks such as:

  • building applications,
  • running tests,
  • validating source code,
  • creating artifacts,
  • checking releases,
  • deployment.

Automation reduces repetitive manual work and makes important checks more consistent.

Instead of relying on someone remembering every release step, the repository can encode much of the process directly.

Continuous Integration

Continuous integration is particularly valuable as projects grow.

A repository can automatically verify new changes before they become part of the stable codebase.

Depending on the project, checks may include:

  • compilation,
  • automated tests,
  • static analysis,
  • dependency validation,
  • packaging.

A failed check provides immediate evidence that a change needs attention.

This is much safer than discovering the problem only after deployment.

GitHub and Android Development

I use Git-based workflows for Android projects as well.

A repository can track:

  • Kotlin source code,
  • Jetpack Compose interfaces,
  • Gradle configuration,
  • Android resources,
  • localization files,
  • application versions.

This provides a clear history of application development and makes it possible to isolate changes between releases.

Generated build artifacts and machine-specific files are excluded where they do not belong in source control.

GitHub and Web Development

For web projects, I use Git to track custom application code, configuration and reusable components.

This is particularly valuable for custom WordPress development where code should not exist only as an anonymous modification on a production server.

I can version changes to:

  • PHP,
  • JavaScript,
  • CSS,
  • custom plugins,
  • themes,
  • configuration,
  • application-specific functionality.

This provides a much safer workflow than editing production code without a development history.

Git and Backend Development

Backend applications also benefit strongly from version control.

I use Git to manage:

  • Python applications,
  • APIs,
  • database-related code,
  • Docker configuration,
  • deployment scripts,
  • environment templates.

Code and infrastructure definitions can therefore evolve together.

Git and Docker

Docker configuration belongs naturally in version control.

Dockerfiles, Compose definitions and related configuration can be stored alongside application code.

This means the repository describes not only how the software works but also how its runtime environment is constructed.

Combined with Git tags, this can help reproduce the environment associated with a particular release.

Ignoring Generated and Sensitive Files

Not everything in a development directory belongs in Git.

I use .gitignore rules to exclude files such as:

  • build output,
  • temporary files,
  • local caches,
  • generated dependencies,
  • IDE-specific data where inappropriate,
  • local environment configuration.

Secrets such as API keys, passwords and production credentials should not be committed to the repository.

I keep sensitive configuration outside source control and use appropriate environment or secret-management mechanisms instead.

Repository Security

A Git repository can preserve deleted content in its history, so accidentally committing a secret is more serious than simply deleting the file in a later commit.

I therefore treat credentials as external configuration from the beginning.

If sensitive data is ever exposed, the correct response is generally to revoke or rotate the credential rather than assuming removing it from the latest version of the repository is sufficient.

Documentation

A repository should be understandable beyond the machine on which it was created.

For appropriate projects, I maintain documentation covering areas such as:

  • project purpose,
  • setup,
  • dependencies,
  • development commands,
  • deployment,
  • important architectural notes.

A good README can dramatically reduce the time required to understand or resume a project later.

Repository Structure

I prefer predictable project structures.

Source code, configuration, documentation and generated files should have clear roles.

A well-organized repository makes it easier to:

  • navigate the project,
  • onboard another developer,
  • automate builds,
  • diagnose problems,
  • maintain the software later.

Repository structure is therefore part of maintainability rather than only a cosmetic decision.

Working with Existing Codebases

Git is particularly valuable when I need to work with an existing project.

Before changing something, I can inspect:

  • previous commits,
  • branches,
  • blame history,
  • tags,
  • release history.

This provides context that may not be obvious from the current code alone.

Understanding why code exists is often just as important as understanding what it currently does.

Refactoring Safely

Version control makes larger refactoring work safer.

I can restructure code in stages while preserving known working states.

If a new approach turns out to be worse, I can compare it with the previous implementation or revert the relevant changes.

This makes experimentation much less risky.

Debugging Regressions

When a feature previously worked and later breaks, Git history can help identify when the regression was introduced.

Comparing revisions allows me to narrow the problem to a specific set of changes.

For difficult cases, Git’s history tools can be significantly faster than debugging the current code without historical context.

Collaboration

Git and GitHub provide a shared technical history when more than one developer works on a project.

Instead of exchanging modified files manually, contributors can work with:

  • branches,
  • commits,
  • pull requests,
  • reviews,
  • issues.

Everyone can see how the project has evolved and which changes are currently proposed.

This greatly reduces ambiguity in collaborative development.

AI-Assisted Development and Git

Version control becomes even more important when AI-assisted development is part of the workflow.

AI can generate or modify substantial amounts of code quickly, but those changes still need to be reviewed and validated.

I use Git as an important safety layer around AI-assisted development.

It allows me to:

  • inspect exact changes,
  • compare generated code with the previous implementation,
  • isolate experiments,
  • revert unsuccessful changes,
  • test changes before merging them.

Fast code generation should not mean uncontrolled code changes.

Git History as Project Knowledge

Over time, a repository becomes more than a copy of the current source code.

It becomes a record of how the application evolved.

That history can answer questions such as:

  • Why was this architecture chosen?
  • When did this behavior change?
  • Which release introduced this feature?
  • What was the previous implementation?
  • Which changes were made together?

Maintaining that history adds long-term value to a project.

Backup Is Not Version Control

Git also provides redundancy, especially when repositories are stored remotely, but I do not treat Git as a complete backup strategy.

Repositories primarily protect source history.

Production databases, uploaded files, generated content and other application data require appropriate backup systems of their own.

Keeping those responsibilities separate prevents false confidence in the recovery strategy.

Git & GitHub in My Technology Stack

I use Git and GitHub alongside technologies such as:

  • JavaScript,
  • TypeScript,
  • PHP,
  • Python,
  • Kotlin,
  • Android,
  • C++,
  • Qt,
  • Docker,
  • Linux,
  • PostgreSQL,
  • WordPress,
  • CI/CD.

They provide the version-control and collaboration layer connecting many otherwise different development environments.

Why I Use Git & GitHub

I use Git and GitHub because reliable software development requires more than writing code that works today.

A project needs a history, identifiable releases, safe experimentation and a clear way to understand how it changes over time.

Git provides that technical history.

GitHub builds collaboration, automation and project management around it.

Together, they give me a development workflow in which changes are traceable, reversible and easier to validate — qualities that become increasingly important as a project grows and continues to evolve.

Back to main page