gitgithubbranchbranching-and-mergingmerge-conflict-resolution

How can I undo someone removing git history on master branch?


I am working on a school project and someone in my group pushed their code very late at night, however there were a couple of major issues:

  1. They pushed straight to master, not on their own branch.
  2. Their folder structure is different than everyone else, their git folder is outside of the project (one directory out compared to everyone else who has their git folder inside the project).
  3. When they pushed they somehow deleted all the other commits in master, in GitHub looking at the master branches history there is only one commit, the one that caused this.

I think those are the major issues. I have been handling most of the git control, and have had to revert a couple of unintentional pushes to master already, this is a whole new beast that I don't know where to begin with.

Where should I start/what should I do? I am still somewhat new to git, so this issue has completed stumped me. Can I change another branch I had to the new master somehow?

I have tried using GitHub to merge my unaffected branch with the master, but it says "master and other_branch are entirely different commit histories" and does not let me do anything else.

I would like to keep the history from "other_branch" if possible.

I have tried checking out the branch in GitHub desktop, and using GitHub studio, but it won't let me pull/push because of the changes. Haven't tried using GitHub command line because currently that seems too daunting given the size of the issue.


Solution

  • It seems like you need to set up some protection rules on the remote's master branch.

    In fact, you cannot prevent someone from completely changing the history of their local branches, but, luckily, you can set up and enforce protection rules on the branches of a remote.

    Setting up Branch Protection Rules

    To set up a branch protection rule, just go to your repository on GitHub and select Settings > Branches > Add branch protection rule. Here, you can define the pattern name of the branch on which the rule must be applied (in your case master). Then enable the options Require a pull request before merging and Require approvals. These will make sure that nobody will be able to push directly on master anymore. The only way to introduce new changes on master is via a pull request, which must be approved first before proceeding with a merge.

    Side note: recover your changes first, and set up the protection rules later, as the following solution implies to force push to the remote repository, which won't be possible after correctly setting up the protection rules.

    Recovering Changes

    Now, to restore your repository while maintaining the other changes, you could create a temporary branch and pull the other changes in there.

    # create new temporary branch
    git branch other_master
    
    # select branch
    git checkout other_master
    
    # pulling current master's changes onto your temp branch
    git pull origin master
    

    At this point, as @Kim has already said in the comments, you could push force your version of master to overwrite the current history on the remote.

    # checking out master branch
    git checkout master
    
    # overwriting the history on the remote's master branch
    git push --force origin master
    

    Now, push your new temporary branch on the remote with the -u option. This will make sure that your local branch other_master will track the remote's branch other_master; otherwise, it would keep tracking the currently overwritten master branch.

    # creating a new branch on the remote with the other master
    git push -u origin other_master
    

    Now, create a new pull request from other_master to either master or the branch of the developer that overwrote master (depends on which flow you want to follow), and merge accordingly.