Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fa9a28b

Browse files
authored
Merge pull request #24662 from tacaswell/doc/git_force
Doc/git force
2 parents 1d2abe7 + cf53019 commit fa9a28b

File tree

1 file changed

+143
-71
lines changed

1 file changed

+143
-71
lines changed

doc/devel/development_workflow.rst

Lines changed: 143 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -170,77 +170,6 @@ To see a linear list of commits for this branch::
170170

171171
git log
172172

173-
.. _rebase-on-main:
174-
175-
Rebasing on ``upstream/main``
176-
-----------------------------
177-
178-
Let's say you thought of some work you'd like to do. You
179-
:ref:`update-mirror-main` and :ref:`make-feature-branch` called
180-
``cool-feature``. At this stage, ``main`` is at some commit, let's call it E.
181-
Now you make some new commits on your ``cool-feature`` branch, let's call them
182-
A, B, C. Maybe your changes take a while, or you come back to them after a
183-
while. In the meantime, ``main`` has progressed from commit E to commit (say) G:
184-
185-
.. code-block:: none
186-
187-
A---B---C cool-feature
188-
/
189-
D---E---F---G main
190-
191-
At this stage you consider merging ``main`` into your feature branch, and you
192-
remember that this here page sternly advises you not to do that, because the
193-
history will get messy. Most of the time you can just ask for a review, and not
194-
worry that ``main`` has got a little ahead. But sometimes, the changes in
195-
``main`` might affect your changes, and you need to harmonize them. In this
196-
situation you may prefer to do a rebase.
197-
198-
``rebase`` takes your changes (A, B, C) and replays them as if they had been
199-
made to the current state of ``main``. In other words, in this case, it takes
200-
the changes represented by A, B, C and replays them on top of G. After the
201-
rebase, your history will look like this:
202-
203-
.. code-block:: none
204-
205-
A'--B'--C' cool-feature
206-
/
207-
D---E---F---G main
208-
209-
See `rebase without tears`_ for more detail.
210-
211-
.. _rebase without tears: https://matthew-brett.github.io/pydagogue/rebase_without_tears.html
212-
213-
To do a rebase on ``upstream/main``::
214-
215-
# Fetch changes from upstream/main
216-
git fetch upstream
217-
# go to the feature branch
218-
git checkout cool-feature
219-
# make a backup in case you mess up
220-
git branch tmp cool-feature
221-
# rebase cool-feature onto main
222-
git rebase --onto upstream/main upstream/main cool-feature
223-
224-
In this situation, where you are already on branch ``cool-feature``, the last
225-
command can be written more succinctly as::
226-
227-
git rebase upstream/main
228-
229-
When all looks good you can delete your backup branch::
230-
231-
git branch -D tmp
232-
233-
If it doesn't look good you may need to have a look at
234-
:ref:`recovering-from-mess-up`.
235-
236-
If you have made changes to files that have also changed in ``main``, this may
237-
generate merge conflicts that you need to resolve - see the `git rebase`_ man
238-
page for some instructions at the end of the "Description" section. There is
239-
some related help on merging in the git user manual - see `resolving a merge`_.
240-
241-
.. _git rebase: https://git-scm.com/docs/git-rebase
242-
.. _resolving a merge: https://schacon.github.io/git/user-manual.html#resolving-a-merge
243-
244173

245174
.. _recovering-from-mess-up:
246175

@@ -358,3 +287,146 @@ and the history looks now like this::
358287

359288
If it went wrong, recovery is again possible as explained :ref:`above
360289
<recovering-from-mess-up>`.
290+
291+
If you have not yet pushed this branch to github, you can carry on as normal,
292+
however if you *have* already pushed this commit see :ref:`force-push` for how
293+
to replace your already published commits with the new ones.
294+
295+
296+
.. _rebase-on-main:
297+
298+
Rebasing on ``upstream/main``
299+
-----------------------------
300+
301+
Let's say you thought of some work you'd like to do. You
302+
:ref:`update-mirror-main` and :ref:`make-feature-branch` called
303+
``cool-feature``. At this stage, ``main`` is at some commit, let's call it E.
304+
Now you make some new commits on your ``cool-feature`` branch, let's call them
305+
A, B, C. Maybe your changes take a while, or you come back to them after a
306+
while. In the meantime, ``main`` has progressed from commit E to commit (say) G:
307+
308+
.. code-block:: none
309+
310+
A---B---C cool-feature
311+
/
312+
D---E---F---G main
313+
314+
At this stage you consider merging ``main`` into your feature branch, and you
315+
remember that this page sternly advises you not to do that, because the
316+
history will get messy. Most of the time you can just ask for a review, and not
317+
worry that ``main`` has got a little ahead. But sometimes, the changes in
318+
``main`` might affect your changes, and you need to harmonize them. In this
319+
situation you may prefer to do a rebase.
320+
321+
``rebase`` takes your changes (A, B, C) and replays them as if they had been
322+
made to the current state of ``main``. In other words, in this case, it takes
323+
the changes represented by A, B, C and replays them on top of G. After the
324+
rebase, your history will look like this:
325+
326+
.. code-block:: none
327+
328+
A'--B'--C' cool-feature
329+
/
330+
D---E---F---G main
331+
332+
See `rebase without tears`_ for more detail.
333+
334+
.. _rebase without tears: https://matthew-brett.github.io/pydagogue/rebase_without_tears.html
335+
336+
To do a rebase on ``upstream/main``::
337+
338+
# Fetch changes from upstream/main
339+
git fetch upstream
340+
# go to the feature branch
341+
git checkout cool-feature
342+
# make a backup in case you mess up
343+
git branch tmp cool-feature
344+
# rebase cool-feature onto main
345+
git rebase --onto upstream/main upstream/main cool-feature
346+
347+
In this situation, where you are already on branch ``cool-feature``, the last
348+
command can be written more succinctly as::
349+
350+
git rebase upstream/main
351+
352+
When all looks good you can delete your backup branch::
353+
354+
git branch -D tmp
355+
356+
If it doesn't look good you may need to have a look at
357+
:ref:`recovering-from-mess-up`.
358+
359+
If you have made changes to files that have also changed in ``main``, this may
360+
generate merge conflicts that you need to resolve - see the `git rebase`_ man
361+
page for some instructions at the end of the "Description" section. There is
362+
some related help on merging in the git user manual - see `resolving a merge`_.
363+
364+
.. _git rebase: https://git-scm.com/docs/git-rebase
365+
.. _resolving a merge: https://schacon.github.io/git/user-manual.html#resolving-a-merge
366+
367+
368+
If you have not yet pushed this branch to github, you can carry on as normal,
369+
however if you *have* already pushed this commit see :ref:`force-push` for how
370+
to replace your already published commits with the new ones.
371+
372+
373+
.. _force-push:
374+
375+
376+
Pushing, with force
377+
-------------------
378+
379+
380+
If you have in some way re-written already pushed history (e.g. via
381+
:ref:`rewriting-commit-history` or :ref:`rebase-on-main`) leaving you with
382+
a git history that looks something like
383+
384+
.. code-block:: none
385+
386+
A'--E cool-feature
387+
/
388+
D---A---B---C origin/cool-feature
389+
390+
where you have pushed the commits ``A,B,C`` to your fork on GitHub (under the
391+
remote name *origin*) but now have the commits ``A'`` and ``E`` on your local
392+
branch *cool-feature*. If you try to push the new commits to GitHub it will
393+
fail with an error that looks like ::
394+
395+
$ git push
396+
Pushing to github.com:origin/matplotlib.git
397+
To github.com:origin/matplotlib.git
398+
! [rejected] cool_feature -> cool_feature (non-fast-forward)
399+
error: failed to push some refs to 'github.com:origin/matplotlib.git'
400+
hint: Updates were rejected because the tip of your current branch is behind
401+
hint: its remote counterpart. Integrate the remote changes (e.g.
402+
hint: 'git pull ...') before pushing again.
403+
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
404+
405+
If this push had succeed then the commits ``A``, ``B``, and ``C`` would no
406+
longer be referenced by any branch and be discarded:
407+
408+
.. code-block:: none
409+
410+
D---A'---E cool-feature, origin/cool-feature
411+
412+
By default ``git push`` helpfully tries to protect you from accidentally
413+
discarding commits by rejecting the push to the remote. When this happens,
414+
GitHub also adds the helpful suggestion to pull the remote changes and then try
415+
pushing again. In some cases, such as if you and a colleague are both
416+
committing and pushing to the same branch, this is a correct course of action.
417+
418+
However, in the case of having intentionally re-written history we *want* to
419+
discard the commits on the remote and replace them with the new-and-improved
420+
versions from our local branch. In this case, what we want to do is ::
421+
422+
$ git push --force-with-lease
423+
424+
which tells git you are aware of the risks and want to do the push anyway. We
425+
recommend using ``--force-with-lease`` over the ``--force`` flag. The
426+
``--force`` will do the push no matter what, whereas ``--force-with-lease``
427+
will only do the push if the remote branch is where the local ``git`` client
428+
thought it was.
429+
430+
Be judicious with force-pushing. It is effectively re-writing published
431+
history and if anyone has fetched the old commits will have a different view
432+
of history which can cause confusion.

0 commit comments

Comments
 (0)