Welcome to Software Development on Codidact!
Will you help us build our independent community of developers helping developers? We're small and trying to grow. We welcome questions about all aspects of software development, from design to code to QA and more. Got questions? Got answers? Got code you'd like someone to review? Please join us.
Post History
The Problem The main problem is that it's important where on the commit graph your branch diverges. I'm going to make some assumptions about the circumstances that are not explicit in your questi...
#5: Post edited
- ## The Problem
- The main problem is that it's important *where* on the commit graph your branch diverges.
- I'm going to make some assumptions about the circumstances that are not explicit in your question:
- 1. When accepting PRs, the upstream project either
- Rebases them- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- ```
- - Or uses a squashed merge
- ```none
- --A--B--C--XYZ' main
- \
- `X--Y--Z first-pr
- ```
2. You made your second branch from the tip of your first one.- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr
- ```
- Taken together, these would give your branch different recent history from the upstream project, even if the content is the same (minus your new PR).
- ## What you should have done
- Before any PR against the current state of a project, you want to sync your clone to that state. The code below assumes that your remote is `origin`, the project's remote is `upstream`, and the primary branch is `main`.
- ```sh
- git fetch upstream
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- ```
- Next, you want to make a branch for your improvements
- ```sh
- git switch --create second-pr upstream/main
- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr
- ```
- Then do your hacking, make commits, and push to your remote.
- ```sh
- git push origin
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `Q--R--S second-pr
- ```
- The branch you push will only have the commits you made on it that are different from the state of `upstream/main` when you created the branch.
- ## What you can do now
- Don't Panic!™ You can recover pretty easily in two different ways. Since the first PR was accepted, your differences from the upstream are probably minimal. Ideally, they're just the changes you have locally.
- ### Make a fresh branch and cherry pick
- If you only have one commit,[^cp-range] you can kind of simulate the "Should have done" section but steal the work you've already done.
- Sync `upstream/main`.
- ```sh
- git fetch upstream
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- Now make a new branch, just as you would have done.
- ```sh
- git switch --create second-pr-take-2 upstream/main
- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And now grab the last commit[^cp-range] from your other branch...
- ```sh
- git cherry-pick second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q' second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And you're ready to push for a new PR, and close the old one!
- ### Rebase your existing branch
- This is probably more common. It has the advantage that it doesn't require a new PR, but it has the downside that it rewrites history. That history won't matter to anyone in most cases, since it's unlikely that people are relying on work from your not-yet-accepted PRs.
- First make sure that you have the latest version of `upstream/main` as normal, but here you *don't `switch` to it.*
- ```sh
- git fetch upstream
- ```
- Next, an optional step that I use to get out of jail free if the rebase doesn't look right. You can do without this tagging if you feel like going into the reflog if something goes wrong. Hopefully it's not even needed.
- ```sh
- git tag tmp/second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr, tmp/second-pr
- ```
- Now for the rebase. The command is actually easy, but sometimes the effects are not.
- ```sh
- git rebase upstream/main
- ```
- This moves your branch to the end of your copy of `upstream/main`, eliminating any already-applied commits along the way. If there are no conflicts, this is seamless. If there are conflicts, consult the second part of [my answer about them][conflict].
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q'-R'-S' second-pr
- \
- `X--Y--Z first-pr
- \
- `Q--R--S tmp/second-pr
- ```
- If it looks good, you can push, but it will have to be a forced-push because the history of your branch is now different from its previous history as known to GitHub. The polite first step is to do this with `--force-with-lease` instead of a raw `--force`. The first version makes sure that it was you who made the last change to your remote branch.
- ```sh
- git push --force-with-lease
- ```
- If that doesn't work, consult with the project owners. They may have rebased or otherwise changed your PR already. There's an option in GitHub for PRs to allow changes from the upstream owners.
- [^cp-range]: In fact, you can also cherry pick *ranges* of commits with `..` syntax if your history is linear. But I will leave that as an exercise for the reader.
- [conflict]: https://software.codidact.com/posts/291969/291970#answer-291970
- ## The Problem
- The main problem is that it's important *where* on the commit graph your branch diverges.
- I'm going to make some assumptions about the circumstances that are not explicit in your question:
- 1. When accepting PRs, the upstream project either
- - Rebases them,
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- ```
- - Merges them
- ```none
- --A--B--C-----------M main
- \ /
- `X--Y--Z` first-pr
- ```
- - Or uses a squashed merge
- ```none
- --A--B--C--XYZ' main
- \
- `X--Y--Z first-pr
- ```
- 2. You made your second branch from the tip of your first one.[^diagram]
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr
- ```
- Taken together, these would give your branch different recent history from the upstream project, even if the content is the same (minus your new PR).
- ## What you should have done
- Before any PR against the current state of a project, you want to sync your clone to that state. The code below assumes that your remote is `origin`, the project's remote is `upstream`, and the primary branch is `main`.
- ```sh
- git fetch upstream
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- ```
- Next, you want to make a branch for your improvements
- ```sh
- git switch --create second-pr upstream/main
- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr
- ```
- Then do your hacking, make commits, and push to your remote.
- ```sh
- git push origin
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `Q--R--S second-pr
- ```
- The branch you push will only have the commits you made on it that are different from the state of `upstream/main` when you created the branch.
- ## What you can do now
- Don't Panic!™ You can recover pretty easily in two different ways. Since the first PR was accepted, your differences from the upstream are probably minimal. Ideally, they're just the changes you have locally.
- ### Make a fresh branch and cherry pick
- If you only have one commit,[^cp-range] you can kind of simulate the "Should have done" section but steal the work you've already done.
- Sync `upstream/main`.
- ```sh
- git fetch upstream
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- Now make a new branch, just as you would have done.
- ```sh
- git switch --create second-pr-take-2 upstream/main
- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And now grab the last commit[^cp-range] from your other branch...
- ```sh
- git cherry-pick second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q' second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And you're ready to push for a new PR, and close the old one!
- ### Rebase your existing branch
- This is probably more common. It has the advantage that it doesn't require a new PR, but it has the downside that it rewrites history. That history won't matter to anyone in most cases, since it's unlikely that people are relying on work from your not-yet-accepted PRs.
- First make sure that you have the latest version of `upstream/main` as normal, but here you *don't `switch` to it.*
- ```sh
- git fetch upstream
- ```
- Next, an optional step that I use to get out of jail free if the rebase doesn't look right. You can do without this tagging if you feel like going into the reflog if something goes wrong. Hopefully it's not even needed.
- ```sh
- git tag tmp/second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr, tmp/second-pr
- ```
- Now for the rebase. The command is actually easy, but sometimes the effects are not.
- ```sh
- git rebase upstream/main
- ```
- This moves your branch to the end of your copy of `upstream/main`, eliminating any already-applied commits along the way. If there are no conflicts, this is seamless. If there are conflicts, consult the second part of [my answer about them][conflict].
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q'-R'-S' second-pr
- \
- `X--Y--Z first-pr
- \
- `Q--R--S tmp/second-pr
- ```
- If it looks good, you can push, but it will have to be a forced-push because the history of your branch is now different from its previous history as known to GitHub. The polite first step is to do this with `--force-with-lease` instead of a raw `--force`. The first version makes sure that it was you who made the last change to your remote branch.
- ```sh
- git push --force-with-lease
- ```
- If that doesn't work, consult with the project owners. They may have rebased or otherwise changed your PR already. There's an option in GitHub for PRs to allow changes from the upstream owners.
- [^diagram]: The diagrams here and below show a rebase of your first PR into upstream, but the steps are the same for any PR acceptance pattern.
- [^cp-range]: In fact, you can also cherry pick *ranges* of commits with `..` syntax if your history is linear. But I will leave that as an exercise for the reader.
- [conflict]: https://software.codidact.com/posts/291969/291970#answer-291970
#4: Post edited
- ## The Problem
- The main problem is that it's important *where* on the commit graph your branch diverges.
- I'm going to make some assumptions about the circumstances that are not explicit in your question:
- 1. When accepting PRs, the upstream project either
- - Rebases them
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- ```
- - Or uses a squashed merge
- ```none
- --A--B--C--XYZ' main
- \
- `X--Y--Z first-pr
- ```
- 2. You made your second branch from the tip of your first one.
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr
- ```
- Taken together, these would give your branch different recent history from the upstream project, even if the content is the same (minus your new PR).
- ## What you should have done
- Before any PR against the current state of a project, you want to sync your clone to that state. The code below assumes that your remote is `origin`, the project's remote is `upstream`, and the primary branch is `main`.
- ```sh
- git fetch upstream
git switch upstream/main- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- ```
- Next, you want to make a branch for your improvements
- ```sh
git switch -b second-pr- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr
- ```
- Then do your hacking, make commits, and push to your remote.
- ```sh
- git push origin
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `Q--R--S second-pr
- ```
- The branch you push will only have the commits you made on it that are different from the state of `upstream/main` when you created the branch.
- ## What you can do now
- Don't Panic!™ You can recover pretty easily in two different ways. Since the first PR was accepted, your differences from the upstream are probably minimal. Ideally, they're just the changes you have locally.
- ### Make a fresh branch and cherry pick
- If you only have one commit,[^cp-range] you can kind of simulate the "Should have done" section but steal the work you've already done.
Sync `upstream/main` and go to it:- ```sh
- git fetch upstream
git switch upstream/main- ```
- ```none
- ---A--B--C--X'-Y'-Z' main (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- Now make a new branch, just as you would have done.
- ```sh
git switch -b second-pr-take-2- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And now grab the last commit[^cp-range] from your other branch...
- ```sh
- git cherry-pick second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q' second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And you're ready to push for a new PR, and close the old one!
- ### Rebase your existing branch
- This is probably more common. It has the advantage that it doesn't require a new PR, but it has the downside that it rewrites history. That history won't matter to anyone in most cases, since it's unlikely that people are relying on work from your not-yet-accepted PRs.
- First make sure that you have the latest version of `upstream/main` as normal, but here you *don't `switch` to it.*
- ```sh
- git fetch upstream
- ```
- Next, an optional step that I use to get out of jail free if the rebase doesn't look right. You can do without this tagging if you feel like going into the reflog if something goes wrong. Hopefully it's not even needed.
- ```sh
- git tag tmp/second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr, tmp/second-pr
- ```
- Now for the rebase. The command is actually easy, but sometimes the effects are not.
- ```sh
- git rebase upstream/main
- ```
- This moves your branch to the end of your copy of `upstream/main`, eliminating any already-applied commits along the way. If there are no conflicts, this is seamless. If there are conflicts, consult the second part of [my answer about them][conflict].
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q'-R'-S' second-pr
- \
- `X--Y--Z first-pr
- \
- `Q--R--S tmp/second-pr
- ```
- If it looks good, you can push, but it will have to be a forced-push because the history of your branch is now different from its previous history as known to GitHub. The polite first step is to do this with `--force-with-lease` instead of a raw `--force`. The first version makes sure that it was you who made the last change to your remote branch.
- ```sh
- git push --force-with-lease
- ```
- If that doesn't work, consult with the project owners. They may have rebased or otherwise changed your PR already. There's an option in GitHub for PRs to allow changes from the upstream owners.
- [^cp-range]: In fact, you can also cherry pick *ranges* of commits with `..` syntax if your history is linear. But I will leave that as an exercise for the reader.
- [conflict]: https://software.codidact.com/posts/291969/291970#answer-291970
- ## The Problem
- The main problem is that it's important *where* on the commit graph your branch diverges.
- I'm going to make some assumptions about the circumstances that are not explicit in your question:
- 1. When accepting PRs, the upstream project either
- - Rebases them
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- ```
- - Or uses a squashed merge
- ```none
- --A--B--C--XYZ' main
- \
- `X--Y--Z first-pr
- ```
- 2. You made your second branch from the tip of your first one.
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr
- ```
- Taken together, these would give your branch different recent history from the upstream project, even if the content is the same (minus your new PR).
- ## What you should have done
- Before any PR against the current state of a project, you want to sync your clone to that state. The code below assumes that your remote is `origin`, the project's remote is `upstream`, and the primary branch is `main`.
- ```sh
- git fetch upstream
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- ```
- Next, you want to make a branch for your improvements
- ```sh
- git switch --create second-pr upstream/main
- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr
- ```
- Then do your hacking, make commits, and push to your remote.
- ```sh
- git push origin
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `Q--R--S second-pr
- ```
- The branch you push will only have the commits you made on it that are different from the state of `upstream/main` when you created the branch.
- ## What you can do now
- Don't Panic!™ You can recover pretty easily in two different ways. Since the first PR was accepted, your differences from the upstream are probably minimal. Ideally, they're just the changes you have locally.
- ### Make a fresh branch and cherry pick
- If you only have one commit,[^cp-range] you can kind of simulate the "Should have done" section but steal the work you've already done.
- Sync `upstream/main`.
- ```sh
- git fetch upstream
- ```
- ```none
- ---A--B--C--X'-Y'-Z' main (HEAD)
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- Now make a new branch, just as you would have done.
- ```sh
- git switch --create second-pr-take-2 upstream/main
- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And now grab the last commit[^cp-range] from your other branch...
- ```sh
- git cherry-pick second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q' second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And you're ready to push for a new PR, and close the old one!
- ### Rebase your existing branch
- This is probably more common. It has the advantage that it doesn't require a new PR, but it has the downside that it rewrites history. That history won't matter to anyone in most cases, since it's unlikely that people are relying on work from your not-yet-accepted PRs.
- First make sure that you have the latest version of `upstream/main` as normal, but here you *don't `switch` to it.*
- ```sh
- git fetch upstream
- ```
- Next, an optional step that I use to get out of jail free if the rebase doesn't look right. You can do without this tagging if you feel like going into the reflog if something goes wrong. Hopefully it's not even needed.
- ```sh
- git tag tmp/second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr, tmp/second-pr
- ```
- Now for the rebase. The command is actually easy, but sometimes the effects are not.
- ```sh
- git rebase upstream/main
- ```
- This moves your branch to the end of your copy of `upstream/main`, eliminating any already-applied commits along the way. If there are no conflicts, this is seamless. If there are conflicts, consult the second part of [my answer about them][conflict].
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q'-R'-S' second-pr
- \
- `X--Y--Z first-pr
- \
- `Q--R--S tmp/second-pr
- ```
- If it looks good, you can push, but it will have to be a forced-push because the history of your branch is now different from its previous history as known to GitHub. The polite first step is to do this with `--force-with-lease` instead of a raw `--force`. The first version makes sure that it was you who made the last change to your remote branch.
- ```sh
- git push --force-with-lease
- ```
- If that doesn't work, consult with the project owners. They may have rebased or otherwise changed your PR already. There's an option in GitHub for PRs to allow changes from the upstream owners.
- [^cp-range]: In fact, you can also cherry pick *ranges* of commits with `..` syntax if your history is linear. But I will leave that as an exercise for the reader.
- [conflict]: https://software.codidact.com/posts/291969/291970#answer-291970
#3: Post edited
- ## The Problem
- The main problem is that it's important *where* on the commit graph your branch diverges.
- I'm going to make some assumptions about the circumstances that are not explicit in your question:
1. The upstream project squashes or rebases their PRs.- 2. You made your second branch from the tip of your first one.
- Taken together, these would give your branch different recent history from the upstream project, even if the content is the same (minus your new PR).
- ## What you should have done
- Before any PR against the current state of a project, you want to sync your clone to that state. The code below assumes that your remote is `origin`, the project's remote is `upstream`, and the primary branch is `main`.
- ```sh
- git fetch upstream
- git switch upstream/main
- ```
- Next, you want to make a branch for your improvements
- ```sh
git switch -b cool-stuff- ```
- Then do your hacking, make commits, and push to your remote.
- ```sh
- git push origin
- ```
- The branch you push will only have the commits you made on it that are different from the state of `upstream/main` when you created the branch.
- ## What you can do now
- Don't Panic!™ You can recover pretty easily in two different ways. Since the first PR was accepted, your differences from the upstream are probably minimal. Ideally, they're just the changes you have locally.
- ### Make a fresh branch and cherry pick
- If you only have one commit,[^cp-range] you can kind of simulate the "Should have done" section but steal the work you've already done.
- Sync `upstream/main` and go to it:
- ```sh
- git fetch upstream
- git switch upstream/main
- ```
- Now make a new branch, just as you would have done.
- ```sh
git switch -b cool-stuff-take-2- ```
- And now grab the last commit[^cp-range] from your other branch...
- ```sh
git cherry-pick cool-stuff- ```
- And you're ready to push for a new PR, and close the old one!
- ### Rebase your existing branch
- This is probably more common. It has the advantage that it doesn't require a new PR, but it has the downside that it rewrites history. That history won't matter to anyone in most cases, since it's unlikely that people are relying on work from your not-yet-accepted PRs.
- First make sure that you have the latest version of `upstream/main` as normal, but here you *don't `switch` to it.*
- ```sh
- git fetch upstream
- ```
- Next, an optional step that I use to get out of jail free if the rebase doesn't look right. You can do without this tagging if you feel like going into the reflog if something goes wrong. Hopefully it's not even needed.
- ```sh
git tag tmp/cool-stuff- ```
- Now for the rebase. The command is actually easy, but sometimes the effects are not.
- ```sh
- git rebase upstream/main
- ```
- This moves your branch to the end of your copy of `upstream/main`, eliminating any already-applied commits along the way. If there are no conflicts, this is seamless. If there are conflicts, consult the second part of [my answer about them][conflict].
- If it looks good, you can push, but it will have to be a forced-push because the history of your branch is now different from its previous history as known to GitHub. The polite first step is to do this with `--force-with-lease` instead of a raw `--force`. The first version makes sure that it was you who made the last change to your remote branch.
- ```sh
- git push --force-with-lease
- ```
- If that doesn't work, consult with the project owners. They may have rebased or otherwise changed your PR already. There's an option in GitHub for PRs to allow changes from the upstream owners.
- [^cp-range]: In fact, you can also cherry pick *ranges* of commits with `..` syntax if your history is linear. But I will leave that as an exercise for the reader.
- [conflict]: https://software.codidact.com/posts/291969/291970#answer-291970
- ## The Problem
- The main problem is that it's important *where* on the commit graph your branch diverges.
- I'm going to make some assumptions about the circumstances that are not explicit in your question:
- 1. When accepting PRs, the upstream project either
- - Rebases them
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- ```
- - Or uses a squashed merge
- ```none
- --A--B--C--XYZ' main
- \
- `X--Y--Z first-pr
- ```
- 2. You made your second branch from the tip of your first one.
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr
- ```
- Taken together, these would give your branch different recent history from the upstream project, even if the content is the same (minus your new PR).
- ## What you should have done
- Before any PR against the current state of a project, you want to sync your clone to that state. The code below assumes that your remote is `origin`, the project's remote is `upstream`, and the primary branch is `main`.
- ```sh
- git fetch upstream
- git switch upstream/main
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- ```
- Next, you want to make a branch for your improvements
- ```sh
- git switch -b second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr
- ```
- Then do your hacking, make commits, and push to your remote.
- ```sh
- git push origin
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `Q--R--S second-pr
- ```
- The branch you push will only have the commits you made on it that are different from the state of `upstream/main` when you created the branch.
- ## What you can do now
- Don't Panic!™ You can recover pretty easily in two different ways. Since the first PR was accepted, your differences from the upstream are probably minimal. Ideally, they're just the changes you have locally.
- ### Make a fresh branch and cherry pick
- If you only have one commit,[^cp-range] you can kind of simulate the "Should have done" section but steal the work you've already done.
- Sync `upstream/main` and go to it:
- ```sh
- git fetch upstream
- git switch upstream/main
- ```
- ```none
- --A--B--C--X'-Y'-Z' main (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- Now make a new branch, just as you would have done.
- ```sh
- git switch -b second-pr-take-2
- ```
- ```none
- --A--B--C--X'-Y'-Z' main, second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And now grab the last commit[^cp-range] from your other branch...
- ```sh
- git cherry-pick second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q' second-pr-take-2 (HEAD)
- \
- `X--Y--Z first-pr
- \
- `Q second-pr
- ```
- And you're ready to push for a new PR, and close the old one!
- ### Rebase your existing branch
- This is probably more common. It has the advantage that it doesn't require a new PR, but it has the downside that it rewrites history. That history won't matter to anyone in most cases, since it's unlikely that people are relying on work from your not-yet-accepted PRs.
- First make sure that you have the latest version of `upstream/main` as normal, but here you *don't `switch` to it.*
- ```sh
- git fetch upstream
- ```
- Next, an optional step that I use to get out of jail free if the rebase doesn't look right. You can do without this tagging if you feel like going into the reflog if something goes wrong. Hopefully it's not even needed.
- ```sh
- git tag tmp/second-pr
- ```
- ```none
- --A--B--C--X'-Y'-Z' main
- \
- `X--Y--Z first-pr
- \
- `Q--R--S second-pr, tmp/second-pr
- ```
- Now for the rebase. The command is actually easy, but sometimes the effects are not.
- ```sh
- git rebase upstream/main
- ```
- This moves your branch to the end of your copy of `upstream/main`, eliminating any already-applied commits along the way. If there are no conflicts, this is seamless. If there are conflicts, consult the second part of [my answer about them][conflict].
- ```none
- --A--B--C--X'-Y'-Z' main
- | \
- | `Q'-R'-S' second-pr
- \
- `X--Y--Z first-pr
- \
- `Q--R--S tmp/second-pr
- ```
- If it looks good, you can push, but it will have to be a forced-push because the history of your branch is now different from its previous history as known to GitHub. The polite first step is to do this with `--force-with-lease` instead of a raw `--force`. The first version makes sure that it was you who made the last change to your remote branch.
- ```sh
- git push --force-with-lease
- ```
- If that doesn't work, consult with the project owners. They may have rebased or otherwise changed your PR already. There's an option in GitHub for PRs to allow changes from the upstream owners.
- [^cp-range]: In fact, you can also cherry pick *ranges* of commits with `..` syntax if your history is linear. But I will leave that as an exercise for the reader.
- [conflict]: https://software.codidact.com/posts/291969/291970#answer-291970
#2: Post edited
- ## The Problem
- The main problem is that it's important *where* on the commit graph your branch diverges.
- I'm going to make some assumptions about the circumstances that are not explicit in your question:
- 1. The upstream project squashes or rebases their PRs.
- 2. You made your second branch from the tip of your first one.
- ## What you should have done
Before any PR against the current state of a project, you want to sync your clone to that state. (The code below assumes that your remote is `origin`, the project's remote is `upstream`, and the primary branch is `main`.)- ```sh
- git fetch upstream
- git switch upstream/main
- ```
- Next, you want to make a branch for your improvements
- ```sh
- git switch -b cool-stuff
- ```
- Then do your hacking, make commits, and push to your remote.
- ```sh
- git push origin
- ```
- The branch you push will only have the commits you made on it that are different from the state of `upstream/main` when you created the branch.
- ## What you can do now
- Don't Panic!™ You can recover pretty easily in two different ways. Since the first PR was accepted, your differences from the upstream are probably minimal. Ideally, they're just the changes you have locally.
- ### Make a fresh branch and cherry pick
If you only have one commit,[^cp-range] you can kind of simulate the "Should have done" section but steal the work.- Sync `upstream/main` and go to it:
- ```sh
- git fetch upstream
- git switch upstream/main
- ```
- Now make a new branch, just as you would have done.
- ```sh
- git switch -b cool-stuff-take-2
- ```
- And now grab the last commit[^cp-range] from your other branch...
- ```sh
- git cherry-pick cool-stuff
- ```
- And you're ready to push for a new PR, and close the old one!
- ### Rebase your existing branch
This is probably more common. It has the advantage that it doesn't require a new PR, but it has the downside that it rewrites history. In most cases, that history won't matter to anyone since it's unlikely that people are relying on work from your not-yet-accepted PRs.First make sure that you have the latest version of `upstream/main` as normal, but you *don't need to `switch` to it.*- ```sh
- git fetch upstream
- ```
Next, an optional step that I use to get out of jail free if something goes wrong. You can do without this tagging if you feel like going into the reflog if something goes wrong. Hopefully it's not even needed.- ```sh
- git tag tmp/cool-stuff
- ```
- Now for the rebase. The command is actually easy, but sometimes the effects are not.
- ```sh
- git rebase upstream/main
- ```
This moves your branch to the end of your copy of `upstream/main`, eliminating any already-applied commits along the way. If there are no conflicts, this is seamless. If there are conflicts, consult the second part of [my other answer][conflict].- If it looks good, you can push, but it will have to be a forced-push because the history of your branch is now different from its previous history as known to GitHub. The polite first step is to do this with `--force-with-lease` instead of a raw `--force`. The first version makes sure that it was you who made the last change to your remote branch.
- ```sh
- git push --force-with-lease
- ```
[^cp-range]: In fact, you can also cherry pick *ranges* of commits if your history is simple. But I will leave that as an exercise for the reader.- [conflict]: https://software.codidact.com/posts/291969/291970#answer-291970
- ## The Problem
- The main problem is that it's important *where* on the commit graph your branch diverges.
- I'm going to make some assumptions about the circumstances that are not explicit in your question:
- 1. The upstream project squashes or rebases their PRs.
- 2. You made your second branch from the tip of your first one.
- Taken together, these would give your branch different recent history from the upstream project, even if the content is the same (minus your new PR).
- ## What you should have done
- Before any PR against the current state of a project, you want to sync your clone to that state. The code below assumes that your remote is `origin`, the project's remote is `upstream`, and the primary branch is `main`.
- ```sh
- git fetch upstream
- git switch upstream/main
- ```
- Next, you want to make a branch for your improvements
- ```sh
- git switch -b cool-stuff
- ```
- Then do your hacking, make commits, and push to your remote.
- ```sh
- git push origin
- ```
- The branch you push will only have the commits you made on it that are different from the state of `upstream/main` when you created the branch.
- ## What you can do now
- Don't Panic!™ You can recover pretty easily in two different ways. Since the first PR was accepted, your differences from the upstream are probably minimal. Ideally, they're just the changes you have locally.
- ### Make a fresh branch and cherry pick
- If you only have one commit,[^cp-range] you can kind of simulate the "Should have done" section but steal the work you've already done.
- Sync `upstream/main` and go to it:
- ```sh
- git fetch upstream
- git switch upstream/main
- ```
- Now make a new branch, just as you would have done.
- ```sh
- git switch -b cool-stuff-take-2
- ```
- And now grab the last commit[^cp-range] from your other branch...
- ```sh
- git cherry-pick cool-stuff
- ```
- And you're ready to push for a new PR, and close the old one!
- ### Rebase your existing branch
- This is probably more common. It has the advantage that it doesn't require a new PR, but it has the downside that it rewrites history. That history won't matter to anyone in most cases, since it's unlikely that people are relying on work from your not-yet-accepted PRs.
- First make sure that you have the latest version of `upstream/main` as normal, but here you *don't `switch` to it.*
- ```sh
- git fetch upstream
- ```
- Next, an optional step that I use to get out of jail free if the rebase doesn't look right. You can do without this tagging if you feel like going into the reflog if something goes wrong. Hopefully it's not even needed.
- ```sh
- git tag tmp/cool-stuff
- ```
- Now for the rebase. The command is actually easy, but sometimes the effects are not.
- ```sh
- git rebase upstream/main
- ```
- This moves your branch to the end of your copy of `upstream/main`, eliminating any already-applied commits along the way. If there are no conflicts, this is seamless. If there are conflicts, consult the second part of [my answer about them][conflict].
- If it looks good, you can push, but it will have to be a forced-push because the history of your branch is now different from its previous history as known to GitHub. The polite first step is to do this with `--force-with-lease` instead of a raw `--force`. The first version makes sure that it was you who made the last change to your remote branch.
- ```sh
- git push --force-with-lease
- ```
- If that doesn't work, consult with the project owners. They may have rebased or otherwise changed your PR already. There's an option in GitHub for PRs to allow changes from the upstream owners.
- [^cp-range]: In fact, you can also cherry pick *ranges* of commits with `..` syntax if your history is linear. But I will leave that as an exercise for the reader.
- [conflict]: https://software.codidact.com/posts/291969/291970#answer-291970
#1: Initial revision
## The Problem The main problem is that it's important *where* on the commit graph your branch diverges. I'm going to make some assumptions about the circumstances that are not explicit in your question: 1. The upstream project squashes or rebases their PRs. 2. You made your second branch from the tip of your first one. ## What you should have done Before any PR against the current state of a project, you want to sync your clone to that state. (The code below assumes that your remote is `origin`, the project's remote is `upstream`, and the primary branch is `main`.) ```sh git fetch upstream git switch upstream/main ``` Next, you want to make a branch for your improvements ```sh git switch -b cool-stuff ``` Then do your hacking, make commits, and push to your remote. ```sh git push origin ``` The branch you push will only have the commits you made on it that are different from the state of `upstream/main` when you created the branch. ## What you can do now Don't Panic!™ You can recover pretty easily in two different ways. Since the first PR was accepted, your differences from the upstream are probably minimal. Ideally, they're just the changes you have locally. ### Make a fresh branch and cherry pick If you only have one commit,[^cp-range] you can kind of simulate the "Should have done" section but steal the work. Sync `upstream/main` and go to it: ```sh git fetch upstream git switch upstream/main ``` Now make a new branch, just as you would have done. ```sh git switch -b cool-stuff-take-2 ``` And now grab the last commit[^cp-range] from your other branch... ```sh git cherry-pick cool-stuff ``` And you're ready to push for a new PR, and close the old one! ### Rebase your existing branch This is probably more common. It has the advantage that it doesn't require a new PR, but it has the downside that it rewrites history. In most cases, that history won't matter to anyone since it's unlikely that people are relying on work from your not-yet-accepted PRs. First make sure that you have the latest version of `upstream/main` as normal, but you *don't need to `switch` to it.* ```sh git fetch upstream ``` Next, an optional step that I use to get out of jail free if something goes wrong. You can do without this tagging if you feel like going into the reflog if something goes wrong. Hopefully it's not even needed. ```sh git tag tmp/cool-stuff ``` Now for the rebase. The command is actually easy, but sometimes the effects are not. ```sh git rebase upstream/main ``` This moves your branch to the end of your copy of `upstream/main`, eliminating any already-applied commits along the way. If there are no conflicts, this is seamless. If there are conflicts, consult the second part of [my other answer][conflict]. If it looks good, you can push, but it will have to be a forced-push because the history of your branch is now different from its previous history as known to GitHub. The polite first step is to do this with `--force-with-lease` instead of a raw `--force`. The first version makes sure that it was you who made the last change to your remote branch. ```sh git push --force-with-lease ``` [^cp-range]: In fact, you can also cherry pick *ranges* of commits if your history is simple. But I will leave that as an exercise for the reader. [conflict]: https://software.codidact.com/posts/291969/291970#answer-291970
