Reputation: 4450
There is this repository on GitHub, let's call it X.
I created a fork of this repository, called FORK_X, also on GitHub.
Then, I cloned FORK_X to my local machine and added a remote pointing to the original repository (X).
So, in my local clone, my remotes are configured as follows:
origin [email protected]:ME/FORK_X.git (fetch)
origin [email protected]:ME/FORK_X.git (push)
upstream [email protected]:THEM/X.git (fetch)
upstream [email protected]:THEM/X.git (push)
When I need to create a pull request (PR):
main
branch is up to date with upstream/main
.main
.X
.In the X repository, multiple PRs from other contributors are frequently opened and updated.
I need an efficient way to test and keep a specific PR from X up to date, without manually repeating commands every time the author pushes new commits.
Currently, I use the following workflow to test a PR:
git remote set-url upstream [email protected]:THEM/X.git
git fetch upstream pull/ID_PR/head:NAME
git checkout NAME
However, whenever new commits are pushed to the PR, I have to manually repeat these steps, deleting and recreating the local branch.
Is there a way to easily test a PR while the author continuously commits without manually running fetch
and checkout
each time?
Upvotes: -3
Views: 75
Reputation: 165396
It should not be necessary to create any intermediate branches. Let's say you've branched from main...
git fetch upstream
git switch my-pr
git rebase upstream/main
git push --force-with-lease
.You could write a script to do this, but it's four trivial commands; I personally don't bother.
Now let's do that with illustrations.
Let's say you branched from upstream's main and have pushed your changes. Since then some new commits have been made upstream (D and E). Your repository and the upstream repository look like this.
upstream
A - B - C - D - E [main]
origin
A - B - C
\
1 - 2 - 3 [my-pr]
local
A - B - C [upstream/main]
\
1 - 2 - 3 [my-pr] [origin/my-pr]
(Note: I did not include a local main nor origin main. I don't ever commit to main in a fork, all work is done in branches and PRs, so main, origin/main, and upstream/main would all point at the same commit. It's simpler to not have main nor origin/main and use upstream/main exclusively. Less to keep up-to-date, less to go wrong.)
Your fork is out is out of date, so it doesn't have D and E yet. We first need to get those locally.
$ git fetch upstream
upstream
A - B - C - D - E [main]
origin
A - B - C
\
1 - 2 - 3 [my-pr]
local
A - B - C - D - E [upstream/main]
\
1 - 2 - 3 [my-pr] [origin/my-pr]
Fetching updated your local upstream/main
. It does not touch your local branches. Now we update your local PR branch by rebasing it onto upstream/main
.
$ git switch my-pr
$ git rebase upstream/main
upstream
A - B - C - D - E [main]
origin
A - B - C
\
1 - 2 - 3 [my-pr]
local
A - B - C - D - E [upstream/main]
\ \
\ 1A - 2A - 3A [my-pr]
\
1 - 2 - 3 [origin/my-pr]
You can also merge if you like, the procedure is the same. I prefer rebasing for updates, it avoids cluttering up the history with merges that are only about updating the branch.
Fix any conflicts, run your local tests. Once you're satisfied, push your new branch.
$ git push --force-with-lease
upstream
A - B - C - D - E [main]
origin
A - B - C - D - E
\
1A - 2A - 3A [my-pr]
local
A - B - C - D - E [upstream/main]
\ \
\ 1A - 2A - 3A [my-pr] [origin/my-pr]
\
1 - 2 - 3
Your old local commits will be garbage collected in a few weeks.
Because the rebase changed the commit IDs in your branch it's necessary to use some sort of --force
. --force-with-lease
is the safer option.
Upvotes: 2