Other effects of `git push -force`?

Questions and answers about forcing git push easy to find ( here are two ). The standard answer looks something like this:

If you need to force git push to be installed, technically you can with the --force , but procedurally you shouldn't , because someone might have pulled out a kitten and is dying somewhere.

I consider this as usual the advice of a sage - a safer route - it is easy to do it again, fixing everything that you broke. But let me say, for example, that I know (magically) that no one has yet taken off a fix. Or even better, this is a private repo, and therefore there is no danger of breaking someone else in a cloned form.

Are there any other [negative] consequences of --force as a result of depression, especially technical consequences? Perhaps this causes excess garbage on the remote control, or it breaks version 1.2.3 of the X Corps analysis tool, or later it becomes more confusing, etc. Something?

EDIT 1: I have my own anecdotal evidence that --force clicking on a private repo does not seem to cause any problems. I am not interested in perception; I am looking for links and / or evidence of this.

+7
git version-control
source share
3 answers

A force press simply tells the remote device to move the given mark (s), even if moving is not a fast forward operation. 1 Fast-forward (optional) results in “abandoned” commits: commits that are no longer available from some link.

(This does not happen when the movement of the label occurs on the part of the graph that is referenced elsewhere. For example, if the xyzzy branch indicates a D fixation in the sequence:

 ABCE <-- plugh \ / D <-- xyzzy 

then it doesn't matter what happens with the plugh label, since the plugh label makes commit D available. Thus, moving xyzzy using non-transition mode, for example to commit C , does not affect commit D . Similarly, deleting an xyzzy label is also completely harmless, at least in terms of the structure of the fixation schedule.)

Remote bare repositories (which are usually pushed to) often do not register all ref updates, so this leads to a quick garbage collection of any abandoned commits. (Note that if you store them in your own repository, you can restore gc'ed commits later, but this requires that you send the data over the network again and put you at risk of data loss if your own repo is corrupted through, say, power failure or computer on fire.)

If you have third-party software that assumes that (some or all) the branch labels move only in fast forward mode, the specified software may fail in interesting ways. I don’t know such software, and if it exists, I would call it “broken”, but people often seem to write broken code and then depend on it.


1 Older versions of git allowed tags to move without forcing if the move was fast, just as branch labels are expected to move. Newer versions (I think they were introduced in 1.8.2, but only from memory) reject any tag movement unless you use force. Of course, you can always delete and then recreate (possibly in another place) the shortcut, and the hook built into it is fine. Thus, there are other ways to move a tag or branch in an arbitrary way, even without power. Just make sure that the parts of the commit graph that you want to keep have some label in each operation.


As for making (your own) more complex process later: yes, it can have such an effect, because you can force the desktop to be forced and thus rearrange the shared-bare-repo. Later, on the “laptop”, you may not be able to remember what you are convinced, and figuring this out can be a little complicated, especially in a large, highly active repository.

Fortunately, there is a new feature in the new git release that uses your logs to find out if an upstream rebase has occurred and when. That is, in the above situation, you could (on a "laptop") ask git to automatically detect which commits were reinstalled in shared-bare-repo and "reinstall" your laptop on this. (This is a generalization of the method used with git pull --rebase today, in git 1.8.x.)

+8
source share

To complement the track with an excellent answer:

A force push can cause problems with subsequent mergers.

Problem:

If you force push A branch, you delete some existing commits from this branch (otherwise you would not need to force). If (as described in torek's answer), these commits also refer to another branch B, then they will remain in that branch. If later you merge two branches A and B, A will contain “new” (forced) commits, and B will make “old” ones.

In this situation, git merge will probably not do what you want. At best, you will get merge conflicts. In the worst case, you will not, but the result will still be wrong. For example, if you removed commit c1 from A using git rebase -i , if c1 is also in B, it will be re-entered if you combine A and B. This may unexpectedly introduce an error: - (.

So, if you force push, make sure you do not remove the commit from other branches / tags (or force push these branches / tags).


Illustration of a remote commit commit

Run the bash script below. The script creates a git repository and a master branch, branch1 with the following commits:

  • good commit (branch1)
  • bad latch (master)
  • Initial

Then he:

  • uses git reset --hard to reject the "bad commit" from the master
  • merges branch1 into master

The output from the script:

 Initialized empty Git repository in .... [... creating commits ...] ### Bad commit in history: * 7549dcc (HEAD, master) bad commit * 31afec8 Initial ### Removing bad commit: HEAD is now at 31afec8 Initial ### Bad commit no longer in history: 31afec8 (HEAD, master) Initial ### Merging branch1: Updating 31afec8..be801e5 Fast-forward 0 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 b create mode 100644 c ### Bad commit is back! be801e5 (HEAD, master, branch1) good commit 7549dcc bad commit 31afec8 Initial 

As you can see, the "bad commit" is removed from the wizard using git reset --hard . However, "bad commit" is still contained in branch1, so when branch1 merges into master, "bad commit" is returned.

Note. This example does not actually force a push, but if you were working with an upstream repo, you would have to force push after deleting a bad commit - the result will be the same.

script:

 #!/bin/bash set -e if [ -e gitrepo ]; then echo "Please remove gitrepo"; exit 1; fi git init gitrepo; cd gitrepo; git config core.pager cat touch a; git add a; git commit -m Initial touch b; git add b; git commit -m "bad commit" git checkout -b branch1; touch c; git add c; git commit -m "good commit" git checkout master echo "### Bad commit in history: " git log --oneline --decorate echo "### Removing bad commit: " git reset --hard HEAD~1 echo "### Bad commit no longer in history: " git log --oneline --decorate echo "### Merging branch1: " git merge branch1 echo "### Bad commit is back!" git log --oneline --decorate 
+6
source share

I use --force in my personal repositories all the time without adverse side effects, because I know when I forced changes and consequences to my code.

The only problem with --force is that it changes the history in the upstream repository, and someone could make changes to the state of the repository before the history changes. This causes problems - and therefore this is not a recommended solution. But even then - these problems can be fixed, they just take a little work.

So, to answer the question - if you just want to share your code with yourself in a private repo, and no one will be affected by these changes, there will be no other side effects.

+2
source share

All Articles