Skip to content

Instantly share code, notes, and snippets.

@pvspain
Last active November 7, 2023 02:20
Show Gist options
  • Save pvspain/92ead8ecd4552bedd643922877d62500 to your computer and use it in GitHub Desktop.
Save pvspain/92ead8ecd4552bedd643922877d62500 to your computer and use it in GitHub Desktop.
howto-process-a-pull-request-locally

How to process a pull-request locally

Formally: How to merge changes from a 'forked' Git repository

Index

Edit your PR config

Create a config file, pull-request-config.sh, substituting the values for the pull request where indicated in chevrons (<>) below, for example: <some-value>

#! /usr/bin/env bash

# How to process a pull request (forked repository) locally
# Instructions: https://gist.github.com/pvspain/92ead8ecd4552bedd643922877d62500

# Fill in the details for the pull request variables - trim all whitespace!

export forkRepoOwner=<fork-repo-owner> 
# For example: export forkRepoOwner=bobthecoder

export forkRepoUrl=<fork-repo-url> 
# For example: export forkRepoUrl=https://github.com/bobthecoder/forkedrepo.git

# The forker's branch name for the pull request
# Often main/master
export prBranch=<fork-repo-pull-request-branch> 
# For example: export prBranch=bobspr

# The local destination branch for an accepted pull request 
# Typically main/master
export localTargetBranch=<local-target-branch> 
# For example: export localTargetBranch=main

# The GitHub Pull Request number
export prNumber=<pull-request-number>
# For example: export prNumber=47

# The tag to identify the head of $localTargetBranch prior to merging
# Default: pre-PR${prNumber}
export prePrTag=pre-PR${prNumber}
# Using our example: pre-PR47

# A (temporary) local branch to inspect the pull request code
# Default: $forkRepoOwner-$prBranch
export localPrBranch=$forkRepoOwner-$prBranch
# Using our example: bobthecoder-bobspr

Load the PR config

Source the config file into a (bash) terminal session...

source ./pull-request-config.sh

Add a remote for the pull request repository

A one-time operation per contributor

# Add a new remote - using fork repo owner's name - as remote name will be unique per repository hub
git remote add "$forkRepoOwner" "$forkRepoUrl"

Load the pull request

# Get their changes
git fetch "$forkRepoOwner" "$prBranch"
# Checkout their changes locally 
git checkout -b "$localPrBranch" "$forkRepoOwner/$prBranch"

QA the changes

  • Run any tests and review the code
  • If you wish to proceed with the pull request...

Merge the changes

  • Checkout the intended target branch for the pull request

    git checkout "$localTargetBranch"
    # Identify the current head of the branch - used as a rollback point if we abort the merge later.
    git tag "$prePrTag"

    Both Option A and Option B below will apply the changes to your repository. We allow fast-forward commits to simplify the branch history where possible, and stage other changes. Neither option will proceed to commit any other changes.

    • Option A: Use the pull-request version wherever there are merge conflicts.

      git merge --no-commit --strategy=ort --strategy-option=theirs "$localPrBranch"

      Note: Conflicts may still occur if a file is deleted in one branch but modified in the other. In this case, you can decide to:

      • Stage the file deletion: git rm <file-spec>, or
      • Revert the file deletion: git add <file-spec>.

      Run git status to review the staged changes

    • Option B: Manually reconcile all conflicts

      git merge --no-commit "$localPrBranch"
      # Stage reconciled conflicts with "git add <file-path>"

QA the merged changes

  • Run any tests and review the merged code

Proceed or abort!

  • If you wish to abort the merge...

    # This will rollback non-fast-forward commits
    git merge --abort
    # This will roll back ff commits, and reset to the previous head
    git reset --hard "$prePrTag"
  • If you wish to accept the merged code, commit the merged changes locally

    git merge --continue
  • Follow your normal process for pushing changes to the upstream repository (GitHub , Bitbucket, GitLab, whatever!) when you're ready.

Clean up

  • Delete the local PR branch
    git branch --delete "$localPrBranch"
    # Remove the tag for the previous head of $localTargetBranch
    git tag --delete "$prePrTag"
  • Optionally, remove the Git remote for the pull request
    git remote rm "$forkRepoOwner"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment