GitHub Issues, Labels, Milestones and Projects for Planning Work

GitHub is not only for code. In this lesson you will track bugs and tasks with Issues, organise them with labels and milestones, and plan sprints and releases with GitHub Projects boards, including a QA-friendly board and bug report template.

๐Ÿ“– What You’ll Learn: Issues, labels, milestones and Projects, creating issues, writing tester-friendly bug reports, mentions, references and task lists, closing issues from PRs, custom labels, milestones for releases, Projects views and fields, built-in automation, and a QA board.


๐Ÿ—‚๏ธ Planning Work on GitHub

Code is only part of a project. Teams also need to track bugs, tasks, ideas and plans. GitHub has built-in tools for that:

ToolUsed for
IssuesIndividual bugs, tasks, questions and feature requests
LabelsCategorising issues and PRs (bug, enhancement, priority)
MilestonesGrouping issues for a release or sprint, with progress and a due date
ProjectsBoards, tables and roadmaps that plan work across issues and PRs

For testers, Issues are often where bug reports live, so writing good ones is a core skill.


๐Ÿž Create an Issue

On the repository, open Issues, New issue (choose a template if the project has them):

FieldTips
TitleSpecific: “Checkout total ignores discount code on mobile Safari”
DescriptionSteps, expected vs actual result, environment, logs or screenshots
AssigneesWho will work on it
Labelsbug, test, priority: high…
Milestonee.g. v2.4.0 or Sprint 18
ProjectsThe board or roadmap that tracks it

A tester-friendly bug report

### Steps to reproduce
1. Log in as standard_user
2. Add "Sauce Labs Backpack" to the cart
3. Apply discount code SAVE10 and go to checkout

### Expected
Total shows $26.99 + tax

### Actual
Total shows $29.99 + tax (discount ignored)

### Environment
- Browser: Safari on iPhone 15 (iOS 18)
- Build: staging, commit a1b2c3d

### Evidence
Screenshot and Playwright trace attached.

Projects make this structure the default with issue templates (CODEOWNERS and templates).


โœ๏ธ Issue Superpowers

FeatureHow
Mention a person@username (they get notified)
Reference another issue or PR#123 (creates a link both ways)
Task list- [ ] Write API test and - [x] Write UI test: clickable checkboxes with progress
Link to codePaste a permalink to a line from GitHub’s file view; it renders as a code snippet
Close from a PRCloses #123, Fixes #123 or Resolves #123 in a PR merged into the default branch
Close from a commitThe same keywords in a commit message pushed to the default branch
Pin important issuesPin issue on the right sidebar

๐Ÿท๏ธ Labels

Every repository starts with default labels: bug, documentation, duplicate, enhancement, good first issue, help wanted, invalid, question, wontfix. Create your own under Issues, Labels, New label, for example:

LabelColour ideaPurpose
type: testPurpleTest automation work
priority: highRedMust be fixed this sprint
area: checkoutBlueFeature area
status: needs-reproYellowBug could not be reproduced yet

๐ŸŽฏ Milestones

Under Issues, Milestones, New milestone, create e.g. v2.4.0 with a due date. Each milestone shows the percentage of closed issues, a quick release-readiness signal for QA.


๐Ÿ“Š GitHub Projects

Projects are flexible planning boards that pull in issues and pull requests from one or many repositories.

  1. Open your profile or organization, Projects, New project.
  2. Choose a template: Board (Kanban), Table or Roadmap.
  3. Add items: paste issue links, or press # in the bottom row and search.
  4. Add custom fields: Status, Priority, Iteration (sprints), Estimate, Test status.
  5. Create views: a board by Status for daily stand-ups, a table grouped by assignee, a roadmap by iteration.

Built-in automation

In the project’s Workflows settings you can enable rules such as:

  • When an item is added, set Status to “Todo”.
  • When an issue is closed or a PR is merged, set Status to “Done”.
  • Auto-add new issues with a certain label from a repository.

A QA board example

Status columnContains
Ready for testPRs merged to the test environment
In testItems a tester is verifying
Bugs foundLinked bug issues
VerifiedTested and passed
DoneReleased

๐Ÿ“ Assignment

  1. In git-practice, create three issues: a bug (using the template above), a feature request and a test task with a task list.
  2. Create custom labels type: test and priority: high and apply them.
  3. Create milestone v0.2.0 and add two issues to it.
  4. Open a PR with Closes #<number>, merge it and confirm the issue closed and the milestone progress changed.
  5. Create a Project board with columns Todo, In progress, In test and Done, add your issues, and enable the “Item closed โ†’ Done” workflow.

โ“ FAQ

๐Ÿค” What are GitHub Issues used for?

Tracking bugs, tasks, feature requests and questions, with discussion, labels, assignees and links to pull requests.

๐Ÿค” How do I close an issue automatically with a pull request?

Include Closes #<number> (or Fixes, Resolves) in the PR description; the issue closes when the PR is merged into the default branch.

๐Ÿค” What is the difference between labels and milestones?

Labels categorise issues (type, priority, area). Milestones group issues for a target such as a release, with a due date and progress.

๐Ÿค” What are GitHub Projects?

Planning tools that show issues and pull requests as boards, tables or roadmaps, with custom fields and automation.

๐Ÿค” How do I write a good bug report on GitHub?

Use a clear title, numbered steps to reproduce, expected vs actual result, environment details and evidence such as screenshots, logs or traces.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

Fork a Repository and Contribute to Open Source on GitHub

Forks let anyone contribute to any public project on GitHub. In this lesson you will fork a repository, set up origin and upstream, open a pull request to the original project, keep your fork in sync and find a good first open-source contribution.

๐Ÿ“– What You’ll Learn: what a fork is, fork vs clone, the full fork workflow, origin and upstream remotes, opening a pull request from a fork, syncing your fork, the gh fork shortcut, finding good first issues, and CONTRIBUTING, code of conduct, CLA and DCO.


๐Ÿด What Is a Fork?

A fork is your own copy of someone else’s repository, under your GitHub account. You have full write access to your fork, even though you cannot push to the original project. Forks are how anyone can contribute to open source:

  1. Fork the project.
  2. Make changes in your fork.
  3. Open a pull request from your fork back to the original project.
CloneFork
Where the copy livesYour computerYour GitHub account
Needs write access to the original to pushYesNo
Used forWorking on repositories you can push toContributing to projects you cannot push to

In practice you fork on GitHub, then clone your fork to your computer.


๐Ÿงญ The Fork Workflow Step by Step

1. Fork on GitHub

Open the project’s page and click Fork (top right). Keep the name, optionally untick “Copy the main branch only”, and click Create fork.

2. Clone your fork and add upstream

git clone git@github.com:your-username/project.git
cd project
git remote add upstream https://github.com/original-owner/project.git
git remote -v
origin    git@github.com:your-username/project.git (fetch)
origin    git@github.com:your-username/project.git (push)
upstream  https://github.com/original-owner/project.git (fetch)
upstream  https://github.com/original-owner/project.git (push)

origin is your fork; upstream is the original project (remotes).

3. Create a branch for your change

git switch -c fix/typo-in-readme
# make the change
git add README.md
git commit -m "Fix typo in installation steps"
git push -u origin fix/typo-in-readme

๐Ÿ’ก Tip: Never work directly on main in a fork. Keep main identical to the original project and use one branch per contribution.

4. Open the pull request

GitHub shows Compare & pull request on your fork. Check that the base repository is the original project (and its main) and the head repository is your fork and branch. Write a clear description, reference the issue (Fixes #123), and submit.

5. Respond to review

Maintainers may ask for changes. Push more commits to the same branch; the PR updates automatically (code review).


๐Ÿ”„ Keep Your Fork Up to Date

The original project keeps moving. Sync your fork before starting new work:

git switch main
git fetch upstream
git merge upstream/main        # or: git rebase upstream/main
git push origin main

Or click Sync fork on your fork’s GitHub page, then git pull locally. To update a feature branch: git rebase main (then git push --force-with-lease), as in git rebase.


โšก Shortcut with the GitHub CLI

gh repo fork original-owner/project --clone    # fork, clone and add upstream in one step
gh pr create --fill                             # open a PR to the original repository

๐ŸŒ Finding Your First Open-Source Contribution

  • Look for issues labelled good first issue or help wanted (search label:"good first issue" on GitHub).
  • Start small: documentation fixes, typos, examples, missing tests.
  • Testers have a natural advantage: reproducing bugs, writing failing tests, and improving test coverage are valuable contributions.

Before you start

FileWhy read it
README.mdHow to set up and run the project
CONTRIBUTING.mdHow the maintainers want contributions: branch names, commit style, tests
CODE_OF_CONDUCT.mdCommunity behaviour rules
Open issues and PRsAvoid duplicating work; comment on an issue before starting a big change

Some projects require a CLA (Contributor License Agreement) or a DCO sign-off (git commit -s adds a “Signed-off-by” line). The PR checks will tell you.


๐Ÿ“ Assignment

  1. Fork any public repository (for example a practice repository from a friend, or GitHub’s own example projects) and clone your fork.
  2. Add the original repository as upstream and confirm with git remote -v.
  3. Create a branch, fix a typo or improve a README, push it and open a pull request to the original repository (or to your own second repository if you prefer not to contact maintainers yet).
  4. Sync your fork’s main with upstream using the commands above and with the Sync fork button.
  5. Find three issues labelled “good first issue” in projects related to testing or Playwright.

โ“ FAQ

๐Ÿค” What is a fork in GitHub?

A copy of another user’s repository in your own GitHub account, which you can change freely and use to propose changes back with a pull request.

๐Ÿค” What is the difference between fork and clone?

A fork is a server-side copy on GitHub under your account. A clone is a local copy on your computer. You usually fork first, then clone your fork.

๐Ÿค” How do I keep my fork updated?

Add the original as upstream, then git fetch upstream, git merge upstream/main on your main branch and git push origin main, or use Sync fork on GitHub.

๐Ÿค” How do I contribute to open source on GitHub?

Find an issue, read CONTRIBUTING.md, fork the repository, make the change on a branch, push it to your fork and open a pull request to the original project.

๐Ÿค” Can I make a pull request without forking?

Only if you have write access to the repository; then you push a branch directly and open the PR from it.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

Code Review on GitHub: Review Pull Requests Like a Professional

Code review is where good teams catch bugs, share knowledge and keep quality high. In this lesson you will review pull requests on GitHub, suggest changes, submit approvals, respond to feedback as an author and follow a practical review checklist.

๐Ÿ“– What You’ll Learn: why code review matters, reviewing a PR step by step, line and multi-line comments, suggested changes, review outcomes, responding as the author, a review checklist including test-code quality, review etiquette, and automating reviews.


๐Ÿ‘€ Why Code Review Matters

Code review means teammates read a change before it is merged. It catches bugs early, spreads knowledge across the team, keeps code consistent and is one of the best learning tools for juniors. On GitHub, code review happens inside pull requests.

For testers, reviewing pull requests is a chance to test earlier: spot missing edge cases, untested paths and risky changes before they reach a test environment.


๐Ÿงญ Reviewing a Pull Request Step by Step

  1. Read the PR title and description: what problem does it solve, and how was it tested?
  2. Check that the CI checks are green.
  3. Open the Files changed tab.
  4. Comment on specific lines, suggest changes and ask questions.
  5. Submit your review with one of three outcomes.

๐Ÿ’ฌ Comment on Code

In Files changed, hover over a line and click the blue +:

  • Click and drag over line numbers (or Shift-click) to comment on several lines.
  • Write the comment, then choose Start a review (recommended) or Add single comment.

Start a review collects all your comments and publishes them together, so the author gets one notification instead of twenty.

Suggest a change directly

In the comment box, click the Add a suggestion button (the ยฑ file icon). GitHub inserts the selected lines in a special “suggestion” block that you edit to the proposed code. The author can then click Commit suggestion, or batch several suggestions into one commit. This is perfect for small fixes such as typos, renamed variables or a better locator.

Useful helpers

  • Tick Viewed on each file to track your progress in large PRs.
  • Use the file filter and the file tree to focus on test files or one folder.
  • Switch between unified and split diff view with the settings gear.
  • Use @username to bring someone into a discussion.

โœ… Submit the Review

Click Finish your review (or Review changes) and choose:

OptionMeaning
CommentGeneral feedback without approving or blocking
ApproveYou are happy for it to be merged
Request changesSomething must be fixed before merging

With branch protection, a PR may require one or more approvals, and “Request changes” blocks the merge until the reviewer re-reviews. CODEOWNERS can request the right reviewers automatically.


๐Ÿ” As the Author: Responding to Review

  1. Reply to each comment: agree, explain, or ask a question.
  2. Push fixes to the same branch; the PR updates and outdated comments are marked as such.
  3. Click Resolve conversation when a thread is settled (or let the reviewer do it, as your team prefers).
  4. Click Re-request review next to the reviewer’s name when you are ready.

๐Ÿ’ก Tip: Do not take review comments personally. Reviewers comment on the code, not on you, and every comment is a chance to improve.


๐Ÿงช What to Look For: A Review Checklist

AreaQuestions to ask
CorrectnessDoes it do what the description says? Any obvious bugs or edge cases missed?
TestsAre there tests for the change? Do they test behaviour, not implementation details?
Test quality (automation PRs)Stable locators, web-first assertions, no hard waits, independent tests (flaky tests)
ReadabilityClear names, small functions, comments where the “why” is not obvious
SecurityNo secrets, tokens or personal data committed (.gitignore)
ScopeOne purpose; unrelated changes moved to another PR
DocsREADME, configuration and changelog updated if needed

๐Ÿค Review Etiquette

โŒ Avoidโœ… Prefer
“This is wrong.”“This misses the empty-cart case. Could we add a test for it?”
“Why did you do this?!”“What was the reason for the 5-second wait? Could expect(...).toBeVisible() replace it?”
Ten comments on styleAgree on a formatter and linter; let tools handle style
Blocking on personal preferencePrefix optional ideas with “nit:” (minor) or “optional:”
Reviewing 2,000 lines at onceAsk for smaller PRs

Praise good work too: “Nice use of a fixture here, much cleaner.”


๐Ÿค– Automating the Boring Parts

  • CI checks run tests and linters on every PR (GitHub Actions).
  • Required status checks block merging until they pass.
  • Dependabot and code scanning add security reviews (security tools).
  • GitHub Copilot can produce a first-pass review and PR summaries (Copilot); a human still owns the decision.

๐Ÿ“ Assignment

  1. Ask a friend (or use a second GitHub account) to open a PR on your git-practice repository, or open one yourself.
  2. Review it with Start a review: add at least one multi-line comment and one suggestion.
  3. Submit a Request changes review, then fix the issues as the author and Re-request review.
  4. Commit a reviewer’s suggestion directly from the PR page.
  5. Approve the PR and merge it.
  6. Write a short code review checklist for your own team or test project.

โ“ FAQ

๐Ÿค” How do I review a pull request on GitHub?

Open the PR, go to Files changed, comment on lines (using Start a review), then click Finish your review and choose Comment, Approve or Request changes.

๐Ÿค” How do I suggest a change in a GitHub review?

In a line comment, click Add a suggestion, edit the proposed code, and submit. The author can apply it with Commit suggestion.

๐Ÿค” What is the difference between Comment, Approve and Request changes?

Comment gives feedback without a decision, Approve signals it is ready to merge, and Request changes asks for fixes and can block merging.

๐Ÿค” How do I re-request a review?

On the PR’s Conversation tab, click the circular arrow next to the reviewer’s name in the Reviewers section.

๐Ÿค” Should testers do code reviews?

Yes. Reviewing PRs lets testers spot missing test cases and risky changes early, and test automation code itself needs review like any other code.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

GitHub Pull Requests Step by Step: Create, Review, Update and Merge

Pull requests are how teams on GitHub propose, discuss, test and merge changes. In this lesson you will open your first pull request, write a description reviewers love, update it after feedback and merge it the right way.

๐Ÿ“– What You’ll Learn: what pull requests are, the full PR workflow, opening a PR and its fields, writing a good description, draft PRs, the PR tabs, updating a PR and handling an out-of-date branch, the three merge methods, PRs with the GitHub CLI, and best practices.


๐Ÿ”ƒ What Is a Pull Request?

A pull request (PR) is a request to merge the changes from one branch into another, usually from a feature branch into main. It is the heart of teamwork on GitHub:

  • Teammates review the code and discuss it line by line.
  • Automated checks (tests, linting, builds) run on the changes in GitHub Actions.
  • The change is merged only when it is approved and the checks pass.

Pull requests also create a permanent record of why a change was made.


๐Ÿงญ The Pull Request Workflow

1. Create a branch      git switch -c feature/login-tests
2. Commit your changes  git commit -m "Add login tests for locked-out users"
3. Push the branch      git push -u origin feature/login-tests
4. Open a pull request  on GitHub (or gh pr create)
5. Review and checks    teammates comment, CI runs
6. Update if needed     more commits on the same branch update the PR
7. Merge                squash, merge commit or rebase
8. Clean up             delete the branch

Steps 1 to 3 are covered in Git Branches and clone, push and pull.


๐Ÿ“ Step 1: Open the Pull Request

After you push a branch, GitHub shows a yellow banner with Compare & pull request. Click it (or open Pull requests, New pull request and choose the branches).

FieldWhat to fill in
baseThe branch you want to merge into (usually main)
compareYour feature branch
TitleA short summary, e.g. “Add login tests for locked-out users”
DescriptionWhat changed, why, how it was tested, screenshots, and linked issues
ReviewersTeammates who should review
AssigneesWho is responsible for the PR (usually you)
Labelse.g. tests, bug, enhancement

A good PR description

## What
Adds login tests for locked-out and invalid users.

## Why
Locked-out users were not covered; see the bug in #42.

## How it was tested
- Ran npx playwright test tests/login.spec.ts in Chromium and Firefox
- All 6 tests pass locally and in CI

Closes #42

Writing Closes #42 (or Fixes or Resolves) links the PR to issue 42 and closes the issue automatically when the PR is merged into the default branch. See Issues and Projects. Teams often provide this structure with a pull request template.


โœ๏ธ Draft Pull Requests

Not ready for review but want feedback or CI results? Choose Create draft pull request from the dropdown on the green button. When finished, click Ready for review.


๐Ÿ” Step 2: The PR Page

TabShows
ConversationDescription, comments, review summary, checks and the merge box
CommitsEvery commit on the branch
ChecksResults of GitHub Actions and other CI
Files changedThe diff, where reviewers comment line by line (code review)

๐Ÿ” Step 3: Update the PR After Feedback

Just commit and push to the same branch; the PR updates automatically:

# fix the review comments, then:
git add tests/login.spec.ts
git commit -m "Use getByRole for the login button"
git push

If main moved on and the PR shows “This branch is out-of-date with the base branch”, click Update branch on GitHub, or locally:

git fetch
git rebase origin/main          # or: git merge origin/main
git push --force-with-lease     # needed after a rebase

Conflicts? GitHub can resolve simple ones in the browser with Resolve conflicts; otherwise resolve them locally (merge conflicts).


โœ… Step 4: Merge the Pull Request

The merge box offers up to three methods (repository admins choose which are allowed):

ButtonWhat happensHistory on main
Create a merge commitAll branch commits plus a merge commitComplete, shows the branch
Squash and mergeAll branch commits combined into one commitOne clean commit per PR
Rebase and mergeBranch commits replayed on top of main, no merge commitLinear, keeps every commit

Many teams use Squash and merge so each PR becomes one readable commit on main. Background: git merge and git rebase.

After merging, click Delete branch, then clean up locally:

git switch main
git pull
git branch -d feature/login-tests
git fetch --prune

โŒจ๏ธ Pull Requests from the Terminal

With the GitHub CLI:

gh pr create --title "Add login tests" --body "Closes #42" --reviewer teammate
gh pr list
gh pr checkout 57          # check out someone else's PR locally to test it
gh pr merge 57 --squash --delete-branch

๐Ÿ’ก Tip: As a tester, gh pr checkout <number> is the fastest way to run a developer’s branch locally and test it before it is merged.


โœ… Pull Request Best Practices

  • Small PRs: under about 400 changed lines are reviewed faster and better.
  • One purpose per PR: do not mix a bug fix, a refactor and a new feature.
  • Clear title and description, with testing notes and screenshots for UI changes.
  • Green checks before asking for review.
  • Respond to every comment, then mark conversations resolved.
  • Protect main so changes can only arrive through reviewed PRs (branch protection).

๐Ÿ“ Assignment

  1. In your git-practice repository on GitHub, create a branch, commit a change, push it and open a pull request with a good description.
  2. Open a second PR as a draft, then mark it ready for review.
  3. Add a new commit to the first PR and watch it update.
  4. Create an issue, then open a PR with Closes #<number> and merge it with Squash and merge; confirm the issue closed.
  5. Make main move ahead, then update an open PR’s branch with Update branch or a local rebase.
  6. Bonus: install the GitHub CLI and create and merge a PR with gh pr create and gh pr merge.

โ“ FAQ

๐Ÿค” What is a pull request in GitHub?

A request to merge changes from one branch into another, with a place for discussion, code review and automated checks before the merge.

๐Ÿค” How do I create a pull request?

Push your branch, click Compare & pull request on GitHub (or Pull requests, New pull request), choose base and compare branches, add a title and description, and click Create pull request.

๐Ÿค” What is the difference between squash and merge and rebase and merge?

Squash and merge combines all PR commits into one commit on the base branch. Rebase and merge replays each commit on top of the base branch without a merge commit.

๐Ÿค” How do I update a pull request?

Push new commits to the same branch. The PR updates automatically.

๐Ÿค” How do I link a pull request to an issue?

Write Closes #<issue-number> in the PR description; the issue closes when the PR is merged into the default branch.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

Git Tags and Versioning: Create, Push and Delete Tags, and GitHub Releases

Tags mark important points in history, such as releases. In this lesson you will learn semantic versioning, create lightweight and annotated tags, push and delete them, check out a tagged version, and publish a GitHub Release.

๐Ÿ“– What You’ll Learn: what tags are and how they differ from branches, semantic versioning, lightweight vs annotated tags, creating, listing and inspecting tags, pushing and deleting tags, checking out a tag and detached HEAD, and GitHub Releases.


๐Ÿท๏ธ What Is a Git Tag?

A tag is a permanent, human-friendly name for a specific commit, most often a release version such as v1.0.0. Unlike a branch, a tag does not move when new commits are added.

BranchTag
Moves with new commitsโœ…โŒ Fixed to one commit
PurposeOngoing workMarking a point in history (release, milestone)
Examplemain, feature/loginv2.4.0, v2.4.1

๐Ÿ”ข Semantic Versioning (SemVer)

Most projects name tags with MAJOR.MINOR.PATCH:

PartIncrease whenExample
MAJORYou make incompatible (breaking) changesv1.4.2 โ†’ v2.0.0
MINORYou add features in a backward-compatible wayv1.4.2 โ†’ v1.5.0
PATCHYou make backward-compatible bug fixesv1.4.2 โ†’ v1.4.3

Pre-releases add a suffix: v2.0.0-beta.1, v2.0.0-rc.1.


๐Ÿ”– Lightweight vs Annotated Tags

LightweightAnnotated
Commandgit tag v1.0.0git tag -a v1.0.0 -m "Release 1.0.0"
StoresJust a pointer to a commitTagger name, email, date and message
Can be signedโŒโœ… (-s)
Recommended forPrivate, temporary markersReleases

โž• Create Tags

git tag -a v1.0.0 -m "First stable release of the test framework"   # tag the current commit
git tag -a v0.9.0 3f2a91c -m "Beta release"                         # tag an older commit
git tag v1.0.0-local                                                  # lightweight tag

๐Ÿ“‹ List and Inspect Tags

git tag                    # all tags, alphabetically
git tag -l "v1.*"          # filter with a pattern
git show v1.0.0            # tag details plus the commit and its diff
git log --oneline --decorate   # tags appear next to commits
tag v1.0.0
Tagger: Asha Verma <asha.verma@example.com>
Date:   Thu Oct 30 12:05:10 2026 +0530

First stable release of the test framework

commit 8b1d4e2c7a9f0b1e2d3c4b5a69788f7e6d5c4b3a (tag: v1.0.0, main)

๐Ÿ“ค Push Tags to GitHub

Tags are not pushed by a normal git push:

git push origin v1.0.0        # push one tag
git push origin --tags        # push all local tags
git push --follow-tags        # push commits and the annotated tags that point to them

๐Ÿ—‘๏ธ Delete or Move a Tag

git tag -d v1.0.0                   # delete locally
git push origin --delete v1.0.0     # delete on GitHub

โš ๏ธ Common mistake: Avoid changing a tag that others may already have fetched. Release tags should be immutable; if a release is broken, publish a new patch version (v1.0.1) instead of moving v1.0.0.


๐Ÿ” Check Out a Tag

git switch --detach v1.0.0           # look at the code as it was at v1.0.0
git switch -c hotfix/1.0.1 v1.0.0    # create a branch from the tag to fix it

Checking out a tag directly puts you in detached HEAD state: you are on a commit, not a branch. Create a branch if you want to commit.


๐Ÿš€ Tags and GitHub Releases

On GitHub, a Release is built on a tag. It adds release notes, a title and downloadable files (binaries, reports, zip archives):

  1. Open the repository, click Releases, then Draft a new release.
  2. Choose an existing tag or create a new one (for example v1.0.0).
  3. Click Generate release notes to list merged pull requests automatically, edit them, and publish.

With the GitHub CLI: gh release create v1.0.0 --generate-notes. Tags can also trigger CI/CD, for example a workflow that runs on push: tags: ['v*'] to deploy a release (deploy with GitHub Actions).


๐Ÿ“ Assignment

  1. In git-practice, create an annotated tag v0.1.0 on the current commit and a lightweight tag checkpoint.
  2. Tag an older commit as v0.0.1 and list tags with git tag -l "v0.*".
  3. Push v0.1.0 to GitHub and find it under Tags; then push all tags.
  4. Create a GitHub Release from v0.1.0 with generated release notes.
  5. Delete checkpoint locally and, if pushed, on GitHub.
  6. Create a hotfix branch from v0.1.0, commit a fix and tag it v0.1.1.

โ“ FAQ

๐Ÿค” What is a tag in Git?

A fixed name for a specific commit, usually used to mark release versions such as v1.0.0.

๐Ÿค” What is the difference between a tag and a branch?

A branch moves forward as you commit; a tag always points to the same commit.

๐Ÿค” How do I push tags to GitHub?

git push origin <tag> for one tag or git push origin --tags for all of them. Normal git push does not send tags.

๐Ÿค” What is the difference between lightweight and annotated tags?

A lightweight tag is just a pointer. An annotated tag also stores the tagger, date and a message and can be signed, so it is recommended for releases.

๐Ÿค” How do I delete a remote tag?

git push origin --delete <tag>, and git tag -d <tag> for the local copy.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

git cherry-pick: Copy Commits from Another Branch (with Examples)

Sometimes you need just one commit from another branch, such as a bug fix for a release. git cherry-pick does exactly that. This lesson shows when to use it, how to pick single commits and ranges, useful options, conflicts and common real-world uses.

๐Ÿ“– What You’ll Learn: what cherry-pick does, when to use it, picking one commit, several commits and ranges, -x, -n, -e and -m options, resolving and aborting cherry-pick conflicts, moving a commit to the right branch, and cherry-pick workflows on GitHub.


๐Ÿ’ What Is git cherry-pick?

git cherry-pick copies one specific commit (or a few) from another branch and applies it to your current branch as a new commit. Unlike merge, it does not bring the whole branch, just the commits you pick.

main:      C1 โ”€โ”€ C2 โ”€โ”€ C3
                  \
feature:           F1 โ”€โ”€ F2 (bug fix) โ”€โ”€ F3

git switch main && git cherry-pick F2

main:      C1 โ”€โ”€ C2 โ”€โ”€ C3 โ”€โ”€ F2'     (same change as F2, new hash)

๐Ÿงช When to Use It

  • Backport a bug fix from main to a release branch (release/2.3) without the new features.
  • Take one useful commit from a teammate’s experimental branch.
  • Recover a commit that ended up on the wrong branch.

๐Ÿ“ Note: Prefer merge or rebase when you want a whole branch. Cherry-picking many commits duplicates history and can cause the same change to appear twice later.


โ–ถ๏ธ Cherry-Pick One Commit

git log --oneline feature/login-fixes    # find the commit hash
# 4d5e6f7 Fix flaky wait in login test

git switch release/2.3
git cherry-pick 4d5e6f7
[release/2.3 9a8b7c6] Fix flaky wait in login test
 Date: Thu Oct 30 11:20:05 2026 +0530
 1 file changed, 2 insertions(+), 3 deletions(-)

๐Ÿ”ข Several Commits and Ranges

git cherry-pick a1b2c3d e4f5a6b          # specific commits, applied in order
git cherry-pick a1b2c3d..e4f5a6b         # range: AFTER a1b2c3d up to e4f5a6b
git cherry-pick a1b2c3d^..e4f5a6b        # range INCLUDING a1b2c3d

โš™๏ธ Useful Options

OptionEffect
-xAdds “(cherry picked from commit …)” to the message: great for traceability on release branches
-n (--no-commit)Applies the changes without committing, so you can combine or edit them first
-e (--edit)Edit the commit message before committing
-m 1Cherry-pick a merge commit, using parent 1 as the base
git cherry-pick -x 4d5e6f7

๐Ÿงฏ Conflicts During Cherry-Pick

If the change does not apply cleanly, Git stops with a conflict:

git cherry-pick 4d5e6f7
# CONFLICT (content): Merge conflict in tests/login.spec.ts
# edit the file to resolve, then:
git add tests/login.spec.ts
git cherry-pick --continue
CommandEffect
git cherry-pick --continueFinish after resolving
git cherry-pick --skipSkip this commit (when picking several)
git cherry-pick --abortCancel and return to the state before

See Resolve Merge Conflicts for resolving the files themselves.


๐Ÿ”„ Move a Commit to the Right Branch

Committed to main by mistake (and not pushed)?

git log --oneline -1               # note the hash, e.g. 7f8e9d0
git switch -c feature/new-tests    # create the correct branch (it starts with the commit)
git switch main
git reset --hard HEAD~1            # remove the commit from main

Or, if the target branch already exists: switch to it, git cherry-pick 7f8e9d0, then remove it from main with git reset --hard HEAD~1 (only if not pushed; see Undo Changes).


๐ŸŒ Cherry-Pick and GitHub

GitHub has no cherry-pick button for pull requests, but the workflow is simple: cherry-pick locally onto a new branch based on the release branch, push it, and open a pull request into the release branch. Many teams automate backports with a bot or a GitHub Action.


๐Ÿ“ Assignment

  1. Create feature/x with three commits. On main, cherry-pick only the second one and check git log --oneline.
  2. Cherry-pick a range of two commits including the first one (A^..B syntax).
  3. Cherry-pick with -x and read the generated message.
  4. Use -n to apply two commits without committing, then make one combined commit.
  5. Cause a conflict during a cherry-pick, resolve it and continue; then repeat and abort.
  6. Commit to main by mistake and move the commit to a new branch.

โ“ FAQ

๐Ÿค” What does git cherry-pick do?

It applies the changes of one or more existing commits onto your current branch as new commits.

๐Ÿค” How do I cherry-pick a commit from another branch?

Find the hash with git log other-branch, switch to your target branch and run git cherry-pick <hash>.

๐Ÿค” How do I cherry-pick multiple commits?

List them (git cherry-pick a b c) or use a range: git cherry-pick A^..B includes A, A..B starts after A.

๐Ÿค” How do I abort a cherry-pick?

git cherry-pick --abort returns to the state before the cherry-pick started.

๐Ÿค” What is the difference between cherry-pick and merge?

Merge brings all commits of a branch and records the integration. Cherry-pick copies only the commits you choose, as new commits with new hashes.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

git stash: Save, List, Apply and Pop Work in Progress

git stash lets you put unfinished work aside, switch tasks and come back later without making messy commits. In this lesson you will save, inspect and restore stashes, handle untracked files and conflicts, and learn when a WIP commit is better.

๐Ÿ“– What You’ll Learn: what git stash is, basic stash and pop, stashing with a message, listing and inspecting stashes, pop vs apply, drop and clear, untracked and partial stashes, git stash branch, conflicts when popping, and common real-world situations.


๐Ÿ“ฆ What Is git stash?

You are halfway through a change when an urgent bug report arrives, or you need to pull, or switch branches, but your work is not ready to commit. git stash saves your uncommitted changes on a stack, cleans your working directory, and lets you bring the changes back later.

Think of it as a clipboard for unfinished work.


โ–ถ๏ธ Basic Usage

git status                 # modified: tests/login.spec.ts
git stash                  # save the changes and clean the working directory
git status                 # nothing to commit, working tree clean

# ...switch branch, pull, fix the urgent bug...

git stash pop              # bring the changes back and remove them from the stash
Saved working directory and index state WIP on main: 8b1d4e2 Add learning goals

๐Ÿท๏ธ Stash with a Message

With several stashes, messages tell them apart:

git stash push -m "WIP: login tests for locked-out user"

๐Ÿ“‹ List, Inspect and Choose Stashes

git stash list
stash@{0}: On feature/login: WIP: login tests for locked-out user
stash@{1}: WIP on main: 8b1d4e2 Add learning goals

stash@{0} is always the most recent.

git stash show stash@{1}        # files changed in a stash
git stash show -p stash@{1}     # the full diff

๐Ÿ” pop vs apply

CommandRestores changesRemoves the stash from the list
git stash popโœ…โœ… (only if it applied without conflicts)
git stash applyโœ…โŒ Keeps it, so you can apply it again elsewhere
git stash apply stash@{1}       # apply a specific stash and keep it
git stash drop stash@{1}        # delete one stash
git stash clear                 # delete ALL stashes (cannot be undone)

โš ๏ธ Common mistake: git stash clear and git stash drop permanently delete stashed work. List with git stash list before cleaning up.


๐Ÿงฉ Untracked and Ignored Files

By default, git stash saves only tracked files (modified and staged). New files stay in the working directory.

CommandAlso stashes
git stash -u (--include-untracked)New, untracked files
git stash -a (--all)Untracked and ignored files
git stash push -- tests/login.spec.tsOnly the listed file(s)
git stash push --stagedOnly staged changes (Git 2.35 and newer)
git stash --keep-indexStash, but leave staged changes in place

๐ŸŒฟ Turn a Stash into a Branch

If the code changed a lot since you stashed and pop would conflict, create a branch from the commit where you stashed and apply it there:

git stash branch feature/login-wip stash@{0}

๐Ÿงฏ Conflicts When Popping

If the stashed changes clash with changes made since, git stash pop reports conflicts like a merge. Resolve them as in Resolve Merge Conflicts, then git add the files. The stash is not dropped automatically when there were conflicts; drop it yourself once you are happy: git stash drop.


๐Ÿงช Typical Situations

SituationCommands
Pull when you have local editsgit stash, git pull, git stash pop
Urgent fix on another branchgit stash -u, git switch main, fix and commit, git switch -, git stash pop
Started work on the wrong branchgit stash, git switch correct-branch, git stash pop
Try an idea quickly and discard itgit stash to save current work, experiment, git restore ., git stash pop

๐Ÿ’ก Tip: Stashes are local and easy to forget. For anything longer than a quick interruption, a WIP commit on a feature branch is often safer: you can tidy it later with interactive rebase.


๐Ÿ“ Assignment

  1. Modify two tracked files, stash them, confirm a clean git status, and restore them with pop.
  2. Create three stashes with messages and list them.
  3. Inspect the second stash with git stash show -p, apply it with apply, and drop it.
  4. Create a new untracked file and show that git stash ignores it but git stash -u saves it.
  5. Simulate “started on the wrong branch”: edit on main, stash, switch to a new branch, pop.
  6. Bonus: create a conflict when popping a stash and resolve it.

โ“ FAQ

๐Ÿค” What does git stash do?

It saves your uncommitted changes in a temporary stack and restores a clean working directory, so you can switch tasks and reapply the changes later.

๐Ÿค” What is the difference between git stash pop and git stash apply?

Both restore the changes. pop also removes the stash from the list; apply keeps it.

๐Ÿค” How do I stash untracked files?

Use git stash -u (or --include-untracked).

๐Ÿค” How do I name a stash?

git stash push -m "your message".

๐Ÿค” Can I recover a dropped stash?

Sometimes. Dropped stashes become unreachable commits; git fsck --unreachable can list them while they still exist. It is much easier not to drop stashes you might need.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

git rebase Explained: Rebase vs Merge, Conflicts and the Golden Rule

Rebase is one of Git’s most powerful and most misunderstood commands. In this lesson you will see exactly what rebasing does, rebase a feature branch, handle conflicts, compare rebase with merge and learn the golden rule that keeps teams safe.

๐Ÿ“– What You’ll Learn: how rebase replays commits, rebasing a feature branch on main, continue, skip and abort, rebase vs merge, the golden rule and force-with-lease, pull –rebase, useful variations like –onto and –autostash, and undoing a rebase with reflog.


๐Ÿงฌ What Does git rebase Do?

git rebase moves a branch so that it starts from a different commit, usually the latest main. Git takes your branch’s commits, sets them aside, updates the base, and replays your commits one by one on top.

Before:                                After: git switch feature && git rebase main
          C3 โ”€โ”€ C4 โ† feature                               C3' โ”€โ”€ C4' โ† feature
         /                                                /
C1 โ”€โ”€ C2 โ”€โ”€ C5 โ”€โ”€ C6 โ† main            C1 โ”€โ”€ C2 โ”€โ”€ C5 โ”€โ”€ C6 โ† main

The replayed commits (C3', C4') have the same changes but new hashes, because their parent changed. The result is a straight, linear history, as if you had started your work after C6.


โ–ถ๏ธ Rebasing Step by Step

git switch feature/login-tests
git fetch
git rebase origin/main          # or: git rebase main (after updating main)
Successfully rebased and updated refs/heads/feature/login-tests.

Then fast-forward main (or open a pull request):

git switch main
git merge feature/login-tests    # a fast-forward: no merge commit needed

๐Ÿงฏ Conflicts During a Rebase

Because commits are replayed one at a time, you may resolve conflicts for each commit:

git rebase main
# CONFLICT (content): Merge conflict in tests/login.spec.ts
# fix the file, then:
git add tests/login.spec.ts
git rebase --continue
CommandWhat it does
git rebase --continueContinue after resolving the current commit’s conflicts
git rebase --skipDrop the current commit and continue
git rebase --abortStop and return to the state before the rebase

How to resolve the conflict itself is explained in Resolve Merge Conflicts.


โš–๏ธ Rebase vs Merge

git mergegit rebase
HistoryPreserved exactly, with merge commitsRewritten into a straight line
Commit hashesUnchangedNew hashes for rebased commits
Merge commitsYes (unless fast-forward)No
Conflict resolutionOnce, for the whole mergePossibly once per replayed commit
Safe on shared, pushed branchesโœ… YesโŒ Not without coordination
Reading historyShows when branches were integratedClean and easy to follow
Typical useIntegrating finished features into mainUpdating your own feature branch with main

A common team approach: rebase your own feature branch on main to keep it up to date and clean, then merge it into main through a pull request.


โš ๏ธ The Golden Rule of Rebasing

โš ๏ธ Common mistake: Do not rebase commits that other people have based work on. Rebasing changes commit hashes; teammates who pulled the old commits will get duplicated commits and confusing conflicts. Rebase only local commits or branches that only you use.

If you rebase a branch you already pushed (your own feature branch), the remote rejects a normal push. Update it safely:

git push --force-with-lease

๐Ÿ” Pull with Rebase

Instead of creating “Merge branch ‘main’ of github.com…” commits every time you pull, replay your local commits on top of the remote:

git pull --rebase
git config --global pull.rebase true    # make it the default (optional)

See git fetch vs git pull.


๐Ÿ› ๏ธ Useful Variations

git rebase -i HEAD~3                       # interactive: squash, reword, reorder (next module)
git rebase --onto main old-base feature    # move a branch to a new base, skipping old-base's commits
git rebase main --autostash                # stash uncommitted changes automatically during the rebase

Interactive rebase gets its own lesson in Advanced Git.


๐Ÿ›Ÿ Undo a Rebase

If a rebase went wrong after it finished, find the branch’s previous position in the reflog and reset to it:

git reflog
# a1b2c3d HEAD@{5}: checkout: moving from main to feature/login-tests
git reset --hard HEAD@{5}

More in git reflog.


๐Ÿ“ Assignment

  1. Create feature/rebase-demo from main and make two commits. Make one commit on main.
  2. Rebase the feature branch onto main and compare git log --oneline --graph --all before and after. Note the changed hashes.
  3. Fast-forward main to the rebased branch.
  4. Repeat, creating a conflict on purpose, and resolve it with git rebase --continue.
  5. Start another rebase and cancel it with git rebase --abort.
  6. Push a feature branch, rebase it, and update the remote with --force-with-lease.

โ“ FAQ

๐Ÿค” What does git rebase do?

It replays the commits of your branch on top of another branch (or commit), giving them a new base and new hashes, which produces a linear history.

๐Ÿค” What is the difference between git merge and git rebase?

Merge combines branches and keeps history as it happened, with merge commits. Rebase rewrites your branch’s commits on top of the target, creating a straight history without merge commits.

๐Ÿค” When should I not use git rebase?

Do not rebase commits that are on a shared branch others are using, such as main or a branch your teammates pulled.

๐Ÿค” How do I abort a rebase?

git rebase --abort returns everything to how it was before the rebase started.

๐Ÿค” Why do I need to force push after a rebase?

Rebasing changes commit hashes, so the remote branch no longer matches. Use git push --force-with-lease for your own branch.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

How to Resolve Merge Conflicts in Git (Step by Step with VS Code)

Merge conflicts look scary, but they follow a simple pattern. In this lesson you will create a conflict on purpose, read the conflict markers, resolve it on the command line and in VS Code, handle special cases and learn habits that prevent painful conflicts.

๐Ÿ“– What You’ll Learn: what causes conflicts, creating a practice conflict, finding conflicted files, reading conflict markers, resolving and finishing a merge, VS Code conflict tools, –ours and –theirs, aborting, other conflict types, and preventing conflicts.


๐Ÿงฏ What Is a Merge Conflict?

A merge conflict happens when two branches changed the same lines of the same file (or one branch edited a file the other deleted) and Git cannot decide which version to keep. Git pauses and asks you to decide.

Conflicts are normal in teamwork. They are not errors, and nothing is lost: both versions are still there.

Conflicts can appear during git merge, git pull, git rebase, git cherry-pick and git stash pop.


๐Ÿงช Create a Conflict to Practise

echo "timeout: 10000" > config.txt
git add config.txt
git commit -m "Add config file"

git switch -c feature/timeout
echo "timeout: 30000" > config.txt
git commit -am "Set timeout to 30 seconds"

git switch main
echo "timeout: 60000" > config.txt
git commit -am "Set timeout to 60 seconds"

git merge feature/timeout
Auto-merging config.txt
CONFLICT (content): Merge conflict in config.txt
Automatic merge failed; fix conflicts and then commit the result.

๐Ÿ” Step 1: See Which Files Conflict

git status
You have unmerged paths.
  (fix conflicts and run "git commit")
  (use "git merge --abort" to abort the merge)

Unmerged paths:
  (use "git add <file>..." to mark resolution)
	both modified:   config.txt

๐Ÿงฉ Step 2: Read the Conflict Markers

Open the file. Git has inserted conflict markers:

<<<<<<< HEAD
timeout: 60000
=======
timeout: 30000
>>>>>>> feature/timeout
MarkerMeaning
<<<<<<< HEADStart of your current branch’s version (here: main)
=======Separator
>>>>>>> feature/timeoutEnd of the incoming branch’s version

โœ๏ธ Step 3: Decide and Edit

Choose one side, the other, or a combination, and delete all three marker lines:

timeout: 45000

๐Ÿ’ก Tip: Do not resolve blindly. Read both versions, understand why each change was made (check git log of each branch), and ask the teammate if unsure. For test code, run the affected tests after resolving.


โœ… Step 4: Mark as Resolved and Finish

git add config.txt        # tells Git the conflict in this file is resolved
git status                # "All conflicts fixed but you are still merging."
git commit                # completes the merge (the message is pre-filled)

For a rebase the finish command is git rebase --continue; for cherry-pick, git cherry-pick --continue.


๐Ÿง‘โ€๐Ÿ’ป Resolving in VS Code

VS Code highlights conflicts and shows clickable actions above each one:

  • Accept Current Change: keep your branch’s version (HEAD).
  • Accept Incoming Change: keep the other branch’s version.
  • Accept Both Changes: keep both, one after the other.
  • Compare Changes: side-by-side view.

You can also open the 3-way Merge Editor (Resolve in Merge Editor) to see “Incoming”, “Current” and the “Result” at once. After saving, stage the file in the Source Control panel and commit. See Git in VS Code.


โšก Take a Whole File from One Side

git checkout --ours config.txt      # keep the current branch's version
git checkout --theirs config.txt    # keep the incoming branch's version
git add config.txt

๐Ÿ“ Note: During a rebase, “ours” and “theirs” are swapped: “ours” is the branch you are rebasing onto, “theirs” is your own commit being replayed.


โ†ฉ๏ธ Not Ready? Abort

git merge --abort          # back to the state before the merge
git rebase --abort
git cherry-pick --abort

๐Ÿงท Other Conflict Types

TypeShown asHow to resolve
Both modifiedboth modifiedEdit markers as above
Modify/deletedeleted by them or deleted by usKeep the file (git add file) or delete it (git rm file)
Both addedboth addedCombine or choose one version
Binary files (images, PDFs)No markersChoose with --ours or --theirs

๐Ÿ›ก๏ธ How to Avoid Painful Conflicts

  • Pull or merge main into your branch often, so differences stay small.
  • Keep branches short-lived and pull requests small.
  • Communicate when you refactor shared files.
  • Use a formatter (for example Prettier) so formatting changes do not collide.
  • Avoid committing generated files (reports, lock files from different tools) by using .gitignore.

๐Ÿ“ Assignment

  1. Recreate the timeout conflict from this lesson and resolve it by hand, then finish the merge.
  2. Create the same conflict again and abort it with git merge --abort.
  3. Create a conflict and resolve it in VS Code with “Accept Both Changes”, then clean up the result.
  4. Create a modify/delete conflict (one branch edits a file, the other deletes it) and resolve it both ways.
  5. Bonus: create a conflict during git rebase and resolve it with git rebase --continue.

โ“ FAQ

๐Ÿค” How do I resolve a merge conflict in Git?

Run git status to find the files, edit each file to the correct content and remove the <<<<<<<, ======= and >>>>>>> markers, then git add the files and git commit.

๐Ÿค” What do <<<<<<< HEAD and >>>>>>> mean?

They mark a conflict. The part after <<<<<<< HEAD is your current branch’s version; the part before >>>>>>> branch is the incoming version, separated by =======.

๐Ÿค” How do I cancel a merge with conflicts?

git merge --abort returns your branch and files to the state before the merge started.

๐Ÿค” How do I accept all incoming changes for a file?

git checkout --theirs file during a merge, then git add file.

๐Ÿค” Why do merge conflicts happen?

Two branches changed the same lines of a file, or one changed a file that the other deleted, so Git cannot combine them automatically.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in

git merge Explained: Fast-Forward, Three-Way, –no-ff and Squash Merges

Merging brings finished work back into main. In this lesson you will learn how Git decides between fast-forward and three-way merges, use the most important merge options, check what will be merged, and clean up afterwards.

๐Ÿ“– What You’ll Learn: how merging works, fast-forward merges, three-way merges and merge commits, –no-ff, –ff-only, –squash and –abort, –no-ff vs squash and GitHub’s merge buttons, checking branches before and after a merge, and cleaning up merged branches.


๐Ÿ”€ What Does Merging Do?

When the work on a branch is finished, you merge it into another branch, usually main. Git combines the histories and the changes. You always merge into the branch you are currently on:

git switch main                 # 1. go to the branch that should receive the changes
git pull                        # 2. make sure it is up to date
git merge feature/login-tests   # 3. bring the feature in

Depending on the history, Git performs one of two kinds of merge.


โฉ Fast-Forward Merge

If main has no new commits since the branch was created, Git simply moves the main pointer forward. No merge commit is created.

Before:                              After git merge feature:
C1 โ”€โ”€ C2 โ† main                      C1 โ”€โ”€ C2 โ”€โ”€ C3 โ”€โ”€ C4 โ† main, feature
        \
         C3 โ”€โ”€ C4 โ† feature
Updating 8b1d4e2..7e2f1a9
Fast-forward
 tests/login.spec.ts | 25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

๐Ÿ”บ Three-Way Merge

If both branches have new commits, Git looks at three snapshots (the common ancestor and the two branch tips) and creates a new merge commit with two parents.

Before:                                After git merge feature:
C1 โ”€โ”€ C2 โ”€โ”€ C5 โ† main                  C1 โ”€โ”€ C2 โ”€โ”€ C5 โ”€โ”€โ”€โ”€ M โ† main
        \                                      \          /
         C3 โ”€โ”€ C4 โ† feature                     C3 โ”€โ”€ C4 โ† feature

Git opens your editor with a default message like “Merge branch ‘feature/login-tests'”; save and close to finish. If both branches changed the same lines, Git stops with a conflict instead; see Resolve Merge Conflicts.


๐ŸŽ›๏ธ Merge Options

CommandResult
git merge featureFast-forward if possible, otherwise a merge commit
git merge --no-ff featureAlways create a merge commit, keeping the branch visible in history
git merge --ff-only featureMerge only if a fast-forward is possible; otherwise stop
git merge --squash featureCombine all branch changes into staged changes; you then make one normal commit
git merge --abortCancel a merge that stopped with conflicts and go back to the state before

–no-ff vs –squash

--no-ff--squash
Commits from the branch kept in main’s historyโœ… All of themโŒ Replaced by one new commit
Merge commitโœ…โŒ
Readable history of mainDetailedCompact, one commit per feature
GitHub equivalent“Create a merge commit”“Squash and merge”

GitHub’s three pull-request merge buttons (merge commit, squash and merge, rebase and merge) map to these strategies; see Pull Requests Step by Step.


๐Ÿ” Check Before and After Merging

git log --oneline main..feature/login-tests   # commits that will come in
git diff main...feature/login-tests           # changes on the branch since it split from main
git branch --merged                           # branches already merged into the current branch
git branch --no-merged                        # branches with unmerged work
git log --oneline --graph --all               # see the result

๐Ÿงน After Merging

git push                              # publish the merged main
git branch -d feature/login-tests     # delete the merged branch locally
git push origin --delete feature/login-tests

๐Ÿงญ Merge vs Rebase (Preview)

Merging preserves history exactly as it happened and is always safe for shared branches. Rebasing rewrites a branch so it looks as if it started from the latest main, giving a linear history. The full comparison is in git rebase and rebase vs merge.


๐Ÿ“ Assignment

  1. Create feature/a from main, make two commits, switch to main and merge. Confirm it was a fast-forward.
  2. Create feature/b, commit on it, then commit something different on main. Merge feature/b and inspect the merge commit with git log --oneline --graph.
  3. Repeat with --no-ff on a branch that could fast-forward and compare the graphs.
  4. Merge a branch with three commits using --squash and commit the result with one message.
  5. Use git branch --merged to find branches you can safely delete, and delete them.

โ“ FAQ

๐Ÿค” How do I merge a branch into main?

Switch to main (git switch main), update it (git pull), then run git merge branch-name and push.

๐Ÿค” What is a fast-forward merge?

A merge where the target branch has no new commits, so Git just moves its pointer forward to the branch tip without creating a merge commit.

๐Ÿค” What does git merge –no-ff do?

It always creates a merge commit, even when a fast-forward is possible, so the feature branch remains visible in history.

๐Ÿค” How do I cancel a merge?

If the merge stopped with conflicts, run git merge --abort. If it already completed and was not pushed, git reset --hard HEAD~1 removes it; if pushed, use git revert -m 1 <merge-commit>.

๐Ÿค” What is the difference between merge and squash merge?

A normal merge keeps every commit from the branch. A squash merge combines them into a single new commit on the target branch.


๐ŸŽฏ Next Steps

๐ŸŽฌ Learn Git and GitHub step by step: watch the series on YouTube!

Subscribe to SqaToolsByDY • Practice on sqatools.in