Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can git rebase completely remove remote history?

As we consider moving from SVN to git at work, a coworker has raised the concern that a malicious or accident-prone developer could use git rebase to delete remote history from our shared repo.

Edit: As pointed out in the answers, entire branches could also be deleted from the remote repo with git push origin :branch-name.

Is this a realistic problem? If so, what approach can we take to prevent it?

like image 335
Matthew Gilliard Avatar asked Jul 15 '11 08:07

Matthew Gilliard


People also ask

Does git rebase lose history?

rebase does not lose any history at all. Every single commit that you used to have is still there.

Does rebasing change history?

Changing older or multiple commits. To modify older or multiple commits, you can use git rebase to combine a sequence of commits into a new base commit. In standard mode, git rebase allows you to literally rewrite history — automatically applying commits in your current working branch to the passed branch head.

Does git rebase affect the remote repository?

No, locally rebasing doesn't change the remote. @jonrsharpe So basically, I have to push to remote branch again after the rebase?

How do I clear my git repository history?

Steps to get to a clean commit history:understand rebase and replace pulling remote changes with rebase to remove merge commits on your working branch. use fast-forward or squash merging option when adding your changes to the target branch. use atomic commits — learn how to amend, squash or restructure your commits.


3 Answers

I tend to agree with your coworker that there is a problem here because:

  • no matter how well you trust your committers, there is always a possibility of human error
  • more onerous review processes (e.g. Gerrit) are not always appropriate
  • restoring from backups can be slow and a PITA

Have you considered the receive.denyNonFastForwards and receive.denyDeletes config parameters? AFAICT these are available in Git 1.6 onwards.

From Pro Git:

If you rebase commits that you’ve already pushed and then try to push again, or otherwise try to push a commit to a remote branch that doesn’t contain the commit that the remote branch currently points to, you’ll be denied. This is generally good policy; but in the case of the rebase, you may determine that you know what you’re doing and can force-update the remote branch with a -f flag to your push command.

To disable the ability to force-update remote branches to non-fast-forward references, set receive.denyNonFastForwards

The other way you can do this is via server-side receive hooks, which I’ll cover in a bit. That approach lets you do more complex things like deny non-fast-forwards to a certain subset of users.

As the author mentions, this rule can also be enforced via a receive hook (which is described later in Pro Git).

These techniques should protect against accidental (or malicious) lost history in your shared repo.

like image 157
joelittlejohn Avatar answered Nov 07 '22 06:11

joelittlejohn


The history can be messed up using rebase, but normally remote repo will not accept the change that modifies the history (unless you use git push --force), but even more, the developer with push permission can delete the branch completely (git push origin :branch-name). So the simple rules are:

  • Do not let push permission to developers you do not trust.

  • When the repo is shared, do not mess with a history, avoid using rebase on past commits. Use merge or cherry-pick instead if you need to add something from different branch, in which case the history will not be affected.

  • You may maintain the policy of not using 'push -f' on shared repo, in which case developer will know that if the push is rejected then something goes wrong (most likely local branch is not up to date with remote) and should resolve the problem locally rather than forcing the push.

Regarding your question how to prevent - use Gerrit revision system, it is like an intermediate step on the way of the commit between developer's local repository and master repo with nice web interface for revision, you may give permissions to push to revision repository to anyone, but the change will be merged into your master branch after verification and approval (which require some permissions you usually grant to core developers). You may see how it looks like on the Mahara project: https://reviews.mahara.org In this particular case, only gerrit bot is allowed to push to master (which is here) and noone else.

like image 20
Ruslan Kabalin Avatar answered Nov 07 '22 07:11

Ruslan Kabalin


There are extensions to enterprise Git servers like Gerrit that will detect history rewrites and branch deletions, will back them up under a special ref so that they can be restored if needed and will not be pruned by garbage collection. Gerrit administrators can still remove selected commits if needed for legal reasons.

like image 1
Johanned Nicolai Avatar answered Nov 07 '22 07:11

Johanned Nicolai