Commits missing from Pull Request merge on target branch
Platform notice: Server and Data Center only. This article only applies to Atlassian products on the Server and Data Center platforms.
Support for Server* products ended on February 15th 2024. If you are running a Server product, you can visit the Atlassian Server end of support announcement to review your migration options.
*Except Fisheye and Crucible
Problem
After merging a Pull Request the merge commit and commits from the source branch cannot be found on the destination branch.
As one example, the feature/abc-123
branch was merged into master
via a Pull Request, but the commits cannot be seen on master
.
Cause
- The pull request was merged with a Squash strategy, which re-creates the changes from the source branch on the target branch without actually pulling any commits from the source branch into the target. If the content changes from the source can be found on the target, there is no problem - this is expected.
- Otherwise, the missing commits are most likely caused by a force push that has removed the commits from the source branch.
Diagnosis
Diagnostic Steps
To check if a force push is the cause of the missing commits, the following steps can be used.
- Identify the merge commit that was created for the Pull Request, this can be found on the Pull Request's Overview. In the screenshot below this is the
e2a3e5fcfef
commit. Run the following cURL command.
curl -u <USER> "https://<BITBUCKET_URL>/rest/api/latest/projects/<PROJECT>/repos/<REPOSITORY>/commits?since=<DESTINATION_BRANCH>&until=<MERGE_COMMIT_HASH>"
Based on the example Pull Request we're using the specific cURL command would be:
curl -u <USER> "https://<BITBUCKET_URL>/rest/api/latest/projects/<PROJECT>/repos/<REPOSITORY>/commits?since=master&until=e2a3e5fcfef"
- If any commits are returned by this REST call, then a force push has occurred.
The REST endpoint that we hit should return an empty values collection if no force push has occurred. The fact that it didn't means something like a rebase followed by a force push has happened on the destination branch. In essence, that URL asks Bitbucket Server "Which commits are reachable from e2a3e5fcfef
that are not on master?" Because the pull request shows that e2a3e5fcfef
is where it was merged and since the pull request was to the master branch, even e2a3e5fcfef
itself should be reachable from master
, meaning no commits should have been returned.
If the missing commit is not related to a pull request or more investigation is needed, follow the steps on Missing Commits in Bitbucket Server.
Resolution
Take a backup of the repository before making any further changes.
Recovering for a force push can be complicated and has several options to choose from. As this is a standard Git operation, we suggest researching the specific situation that has occurred to determine the best course for fixing the issue. A basic example of how to recover is provided below. The force push may have been intentional and therefore no action is required.
If you know the commit that the destination branch was pointed to before the force push occurred, the branch can be reset to this commit hash and pushed back up to the server. For example, if we knew that the head of master
was at c783a47 before the force push, the following can be used to reset master
to that commit.
git checkout master
git reset --hard c783a47
git push --force origin master
Note that this will undo all changes to the master
branch since the force push. This could be disastrous if lots of relevant changes occurred in the mean time.
Another option might be to simple re-merge the PR changes from the source branch into the target branch. However, be careful that you might be merging more than just the PR commits. All commits that are listed in the response from the diagnostic step above will be added back to the target branch.
git checkout master
git merge feature/abc-123
git push origin master
A third option might be to cherry-pick only the commits you need onto the target branch. Details on this can be found in the Git documentation for cherry-pick.