-
-
Notifications
You must be signed in to change notification settings - Fork 7.9k
Doc/git force #24662
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Doc/git force #24662
Changes from all commits
d905955
58ac02d
b9d9881
3079944
446eff4
82932e8
cf53019
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -170,77 +170,6 @@ To see a linear list of commits for this branch:: | |||||||||
|
||||||||||
git log | ||||||||||
|
||||||||||
.. _rebase-on-main: | ||||||||||
|
||||||||||
Rebasing on ``upstream/main`` | ||||||||||
----------------------------- | ||||||||||
|
||||||||||
Let's say you thought of some work you'd like to do. You | ||||||||||
:ref:`update-mirror-main` and :ref:`make-feature-branch` called | ||||||||||
``cool-feature``. At this stage, ``main`` is at some commit, let's call it E. | ||||||||||
Now you make some new commits on your ``cool-feature`` branch, let's call them | ||||||||||
A, B, C. Maybe your changes take a while, or you come back to them after a | ||||||||||
while. In the meantime, ``main`` has progressed from commit E to commit (say) G: | ||||||||||
|
||||||||||
.. code-block:: none | ||||||||||
|
||||||||||
A---B---C cool-feature | ||||||||||
/ | ||||||||||
D---E---F---G main | ||||||||||
|
||||||||||
At this stage you consider merging ``main`` into your feature branch, and you | ||||||||||
remember that this here page sternly advises you not to do that, because the | ||||||||||
history will get messy. Most of the time you can just ask for a review, and not | ||||||||||
worry that ``main`` has got a little ahead. But sometimes, the changes in | ||||||||||
``main`` might affect your changes, and you need to harmonize them. In this | ||||||||||
situation you may prefer to do a rebase. | ||||||||||
|
||||||||||
``rebase`` takes your changes (A, B, C) and replays them as if they had been | ||||||||||
made to the current state of ``main``. In other words, in this case, it takes | ||||||||||
the changes represented by A, B, C and replays them on top of G. After the | ||||||||||
rebase, your history will look like this: | ||||||||||
|
||||||||||
.. code-block:: none | ||||||||||
|
||||||||||
A'--B'--C' cool-feature | ||||||||||
/ | ||||||||||
D---E---F---G main | ||||||||||
|
||||||||||
See `rebase without tears`_ for more detail. | ||||||||||
|
||||||||||
.. _rebase without tears: https://matthew-brett.github.io/pydagogue/rebase_without_tears.html | ||||||||||
|
||||||||||
To do a rebase on ``upstream/main``:: | ||||||||||
|
||||||||||
# Fetch changes from upstream/main | ||||||||||
git fetch upstream | ||||||||||
# go to the feature branch | ||||||||||
git checkout cool-feature | ||||||||||
# make a backup in case you mess up | ||||||||||
git branch tmp cool-feature | ||||||||||
# rebase cool-feature onto main | ||||||||||
git rebase --onto upstream/main upstream/main cool-feature | ||||||||||
|
||||||||||
In this situation, where you are already on branch ``cool-feature``, the last | ||||||||||
command can be written more succinctly as:: | ||||||||||
|
||||||||||
git rebase upstream/main | ||||||||||
|
||||||||||
When all looks good you can delete your backup branch:: | ||||||||||
|
||||||||||
git branch -D tmp | ||||||||||
|
||||||||||
If it doesn't look good you may need to have a look at | ||||||||||
:ref:`recovering-from-mess-up`. | ||||||||||
|
||||||||||
If you have made changes to files that have also changed in ``main``, this may | ||||||||||
generate merge conflicts that you need to resolve - see the `git rebase`_ man | ||||||||||
page for some instructions at the end of the "Description" section. There is | ||||||||||
some related help on merging in the git user manual - see `resolving a merge`_. | ||||||||||
|
||||||||||
.. _git rebase: https://git-scm.com/docs/git-rebase | ||||||||||
.. _resolving a merge: https://schacon.github.io/git/user-manual.html#resolving-a-merge | ||||||||||
|
||||||||||
|
||||||||||
.. _recovering-from-mess-up: | ||||||||||
|
||||||||||
|
@@ -358,3 +287,146 @@ and the history looks now like this:: | |||||||||
|
||||||||||
If it went wrong, recovery is again possible as explained :ref:`above | ||||||||||
<recovering-from-mess-up>`. | ||||||||||
|
||||||||||
If you have not yet pushed this branch to github, you can carry on as normal, | ||||||||||
however if you *have* already pushed this commit see :ref:`force-push` for how | ||||||||||
to replace your already published commits with the new ones. | ||||||||||
|
||||||||||
|
||||||||||
.. _rebase-on-main: | ||||||||||
|
||||||||||
Rebasing on ``upstream/main`` | ||||||||||
----------------------------- | ||||||||||
|
||||||||||
Let's say you thought of some work you'd like to do. You | ||||||||||
:ref:`update-mirror-main` and :ref:`make-feature-branch` called | ||||||||||
``cool-feature``. At this stage, ``main`` is at some commit, let's call it E. | ||||||||||
Now you make some new commits on your ``cool-feature`` branch, let's call them | ||||||||||
A, B, C. Maybe your changes take a while, or you come back to them after a | ||||||||||
while. In the meantime, ``main`` has progressed from commit E to commit (say) G: | ||||||||||
|
||||||||||
.. code-block:: none | ||||||||||
|
||||||||||
A---B---C cool-feature | ||||||||||
/ | ||||||||||
D---E---F---G main | ||||||||||
|
||||||||||
At this stage you consider merging ``main`` into your feature branch, and you | ||||||||||
remember that this page sternly advises you not to do that, because the | ||||||||||
history will get messy. Most of the time you can just ask for a review, and not | ||||||||||
worry that ``main`` has got a little ahead. But sometimes, the changes in | ||||||||||
``main`` might affect your changes, and you need to harmonize them. In this | ||||||||||
situation you may prefer to do a rebase. | ||||||||||
|
||||||||||
``rebase`` takes your changes (A, B, C) and replays them as if they had been | ||||||||||
made to the current state of ``main``. In other words, in this case, it takes | ||||||||||
the changes represented by A, B, C and replays them on top of G. After the | ||||||||||
rebase, your history will look like this: | ||||||||||
|
||||||||||
.. code-block:: none | ||||||||||
|
||||||||||
A'--B'--C' cool-feature | ||||||||||
/ | ||||||||||
D---E---F---G main | ||||||||||
|
||||||||||
See `rebase without tears`_ for more detail. | ||||||||||
|
||||||||||
.. _rebase without tears: https://matthew-brett.github.io/pydagogue/rebase_without_tears.html | ||||||||||
|
||||||||||
To do a rebase on ``upstream/main``:: | ||||||||||
|
||||||||||
# Fetch changes from upstream/main | ||||||||||
git fetch upstream | ||||||||||
# go to the feature branch | ||||||||||
git checkout cool-feature | ||||||||||
# make a backup in case you mess up | ||||||||||
git branch tmp cool-feature | ||||||||||
# rebase cool-feature onto main | ||||||||||
git rebase --onto upstream/main upstream/main cool-feature | ||||||||||
|
||||||||||
In this situation, where you are already on branch ``cool-feature``, the last | ||||||||||
command can be written more succinctly as:: | ||||||||||
|
||||||||||
git rebase upstream/main | ||||||||||
|
||||||||||
When all looks good you can delete your backup branch:: | ||||||||||
|
||||||||||
git branch -D tmp | ||||||||||
|
||||||||||
If it doesn't look good you may need to have a look at | ||||||||||
:ref:`recovering-from-mess-up`. | ||||||||||
|
||||||||||
If you have made changes to files that have also changed in ``main``, this may | ||||||||||
generate merge conflicts that you need to resolve - see the `git rebase`_ man | ||||||||||
page for some instructions at the end of the "Description" section. There is | ||||||||||
some related help on merging in the git user manual - see `resolving a merge`_. | ||||||||||
|
||||||||||
.. _git rebase: https://git-scm.com/docs/git-rebase | ||||||||||
.. _resolving a merge: https://schacon.github.io/git/user-manual.html#resolving-a-merge | ||||||||||
|
||||||||||
|
||||||||||
If you have not yet pushed this branch to github, you can carry on as normal, | ||||||||||
however if you *have* already pushed this commit see :ref:`force-push` for how | ||||||||||
to replace your already published commits with the new ones. | ||||||||||
|
||||||||||
|
||||||||||
.. _force-push: | ||||||||||
|
||||||||||
|
||||||||||
Pushing, with force | ||||||||||
------------------- | ||||||||||
|
||||||||||
|
||||||||||
If you have in some way re-written already pushed history (e.g. via | ||||||||||
tacaswell marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||||||
:ref:`rewriting-commit-history` or :ref:`rebase-on-main`) leaving you with | ||||||||||
a git history that looks something like | ||||||||||
|
||||||||||
.. code-block:: none | ||||||||||
|
||||||||||
A'--E cool-feature | ||||||||||
/ | ||||||||||
D---A---B---C origin/cool-feature | ||||||||||
|
||||||||||
where you have pushed the commits ``A,B,C`` to your fork on GitHub (under the | ||||||||||
remote name *origin*) but now have the commits ``A'`` and ``E`` on your local | ||||||||||
branch *cool-feature*. If you try to push the new commits to GitHub it will | ||||||||||
fail with an error that looks like :: | ||||||||||
|
||||||||||
$ git push | ||||||||||
Pushing to github.com:origin/matplotlib.git | ||||||||||
To github.com:origin/matplotlib.git | ||||||||||
! [rejected] cool_feature -> cool_feature (non-fast-forward) | ||||||||||
error: failed to push some refs to 'github.com:origin/matplotlib.git' | ||||||||||
hint: Updates were rejected because the tip of your current branch is behind | ||||||||||
hint: its remote counterpart. Integrate the remote changes (e.g. | ||||||||||
hint: 'git pull ...') before pushing again. | ||||||||||
hint: See the 'Note about fast-forwards' in 'git push --help' for details. | ||||||||||
|
||||||||||
If this push had succeed then the commits ``A``, ``B``, and ``C`` would no | ||||||||||
longer be referenced by any branch and be discarded: | ||||||||||
|
||||||||||
.. code-block:: none | ||||||||||
|
||||||||||
D---A'---E cool-feature, origin/cool-feature | ||||||||||
|
||||||||||
By default ``git push`` helpfully tries to protect you from accidentally | ||||||||||
discarding commits by rejecting the push to the remote. When this happens, | ||||||||||
GitHub also adds the helpful suggestion to pull the remote changes and then try | ||||||||||
pushing again. In some cases, such as if you and a colleague are both | ||||||||||
committing and pushing to the same branch, this is a correct course of action. | ||||||||||
|
||||||||||
However, in the case of having intentionally re-written history we *want* to | ||||||||||
discard the commits on the remote and replace them with the new-and-improved | ||||||||||
versions from our local branch. In this case, what we want to do is :: | ||||||||||
|
||||||||||
$ git push --force-with-lease | ||||||||||
|
||||||||||
which tells git you are aware of the risks and want to do the push anyway. We | ||||||||||
recommend using ``--force-with-lease`` over the ``--force`` flag. The | ||||||||||
``--force`` will do the push no matter what, whereas ``--force-with-lease`` | ||||||||||
will only do the push if the remote branch is where the local ``git`` client | ||||||||||
thought it was. | ||||||||||
|
||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
.. code-block:: none
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I see what you mean, working on it. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Totally optional - I was about to merge, but thought it would be nice to the back to the example. |
||||||||||
Be judicious with force-pushing. It is effectively re-writing published | ||||||||||
history and if anyone has fetched the old commits will have a different view | ||||||||||
of history which can cause confusion. |
Uh oh!
There was an error while loading. Please reload this page.