All version control systems (clearcase, subversion, CVS, git) history can be changed if you have access to the history. Git being distributed, you have a copy (i.e. fork) of the entire history. You can alter the history (see @mrks^1 answer) of your own fork only.
When you want to distribute back your copy, to push your changes to another fork, with --force
you can thus overwrite the target history:
- onlyif you have write access to the target remote fork
- onlyif the remote branch is not set as readonly
- any existing fork (except your current one) will notice the overwritten of the history and will ask you what to do (i.e. merge).
This is usually what is made in organizations to avoid other users to overwrite the history. And usually only the branch related to main production history path (e.g. branch = prod, production, master etc). This would be part of defining a workflow.
Many organizations^2 that have github mirrors have this setup, to make sure Github itself (intentionally or not) doesn't overwrites history, for example.