Because Stash doesn't allow users to edit the commit messages when merging pull requests, and because Stash uses the default commit message generated when squashing a branch onto another and thus the message is a sum total of all commit messages on that branch, we perform squashed merges manually.
However, if the source branch has more than one commit on it, the pull request is not marked as "remotely merged" when the Branch B is squashed onto Branch A and A is pushed to the remote. Even when I include the boilerplate text that Stash adds to pull request merge messages such as "Merge pull request #27 in FUBAR/adapter from feature/2.3-FUBAR-395-FuBar-FileMetrics-Payload to develop" or include a list of all of the shortened commit hashes ("git log --pretty=format:'%h'"), the pull request is still set to open after I push Branch A, now with a single squashed commit representing the merged pull request, to the remote.
I understand that Stash probably looks for the commit IDs on Branch A that are members of the pull request for Branch B, and if they appear in both places Stash will likely consider the pull request merged. The question is, what happens when those commit IDs disappear because you've squashed them? Clearly Stash can handle it internally since we have our pull request behavior set to ff-only-squash, and when we click the Merge button Stash knows it's merged the thing. But again, because of the noisy commit message generated, we merge by hand. We just need to know how to let Stash know it's been merged.
When a push is received that updates either the source or target branch of a pull request, Stash updates the pull request. As part of this 'rescoping' logic, it checks:
In your case, I assume you're doing the following locally:
git checkout target-branch git merge --ff-only --squash source-branch git commit -m "Your custom message" git push origin HEAD
This only updates the target branch; the source branch is unchanged and Stash will still see unmerged commits (the original commits prior to squashing) and keep the pull request open. It will rescope the pull request, which should result in an empty diff.
If you change your command a little bit, Stash will be able to recognize the fact that your pull request has been merged remotely:
git checkout target-branch git merge --ff-only --squash source-branch git commit -m "Your custom message" git push origin HEAD git checkout -B source-branch git push --force origin HEAD
The last two lines will recreate source-branch at the squashed commit. You'll have to force-push that branch to update it on the server because it's not a fast-forward merge (even though the diff is empty).
I hope this explains the way Stash does 'remote merge' detection!
Thanks for the help! I think on line #5 of your suggested help you actually mean:
git checkout -B target-branch
The man page for git-checkout states "If -B is given, <new_branch> is created if it doesn't exist; otherwise, it is reset" whereas there is no -B option for git-branch.
Also, the last line of the suggested help might need to include the remote:
git push --force origin HEAD
However, when I do these things they don't actually work:
akutz@pax:vcopsadapter$ git checkout -B develop Reset branch 'develop' Your branch is up-to-date with 'origin/develop'. akutz@pax:vcopsadapter$ git push --force origin HEAD Everything up-to-date
No matter the variations I try, the last command always indicates everything is up to date.
Yeah, you're right about the checkout and providing a remote on the force push. I've edited my answer to reflect that.
I've just tested the steps and they work for me. Here's a script of what I've done:
# First create a new repo in Stash git init test-repo git remote add origin http://localhost:7990/stash/scm/proj/test.git echo test > test git add test git commit -m "Initial commit" git checkout -b develop echo testing >> test && git commit -am "Change" echo testing >> test && git commit -am "Change" git push origin --all # create pull request in Stash git checkout master git merge --ff-only --squash develop git commit -m "Squashed changes" git push origin HEAD # verify pull request in Stash - still open, diff is empty git checkout -B develop git push --force origin HEAD # verify pull request in Stash - closed, marked as merged remotely
I'll try that as well. You know, I wonder if it was because the open pull request I tried it on only had a single commit on the source branch. It didn't need a squash, but I did it anyway just to see if the suggestion worked. I wonder if the scenario with squashing a single commit doesn't work. I mean, at that point I'm really just changing the commit ID of a single commit.
The other difference is that developers often rebase their feature branches from develop prior to opening a pull request or often after they open the pull request. However, the pull requests *do* update themselves when a developer rebases the branch for the pull request. For example, it will say 12 added, 12 deleted. Still, I don't know if that could cause issues.
Like I said, I'll create a new repo and try your steps on our set up. I do have the following configured in the stash propreties file:
# The default merge policy for the server is to only accept pull # requests if they are fast-foward only capable and then to process # them as squashed commits. plugin.stash-scm-git.pullrequest.merge.strategy=squash-ff-only
Would that have an effect on how Stash resolve the pull request if it's merged remotely?
Re: only a single commit, it shouldn't matter. Perhaps you forgot to add the --squash option on the merge command?
Re: the plugin.stash-scm-git.pullrequest.merge.strategy=squash-ff-only option, that option only affects the merge Stash does when you merge the pull request through the UI. It should not matter for remotely merged pull requests.
I also have the Workzone plug-in installed. I wonder if that affects the remote merge logic? For the repo in question the only setting I have enabled on Workzone are the automatic branch reviewers and to automatically withdraw any approvals for pull requests if a change is pushed to a branch with an open pull request.
That worked! I misunderstood your original instructions:
git checkout target-branch git merge --ff-only --squash source-branch git commit -m "Your custom message" git push origin HEAD git checkout -B target-branch git push --force origin HEAD
Or rather I guess maybe they had an error. Line #5 should have actually been "git checkout -B source-branch"
In your last script you checked out and reset develop, and in your latest example that was the source branch. That's when I realized that the original instructions had me reset the target branch. So I tried the script and reset the source branch and force pushed it after I performed the squash and it worked perfectly!
I believe a squashed merge commit is different from a normal merge commit resulting from a non-fast-forward merge. I think a squashed merge commit does not reference the source branch as one of its parents.
From the Git docs: "Produce the working tree and index state as if a real merge happened (except for the merge information)"
So if instead of doing `git merge --squash` you were to instead do `git merge --no-ff --no-commit`, you would be able to edit your merge commit message and retain the merge metadata that would allow Stash to link things together.
And more specifically, I don't want all of the history from the feature branch, hence the squashed commit. When you perform a merge with --no-commit all you're doing is giving yourself the ability to edit the merge commit message. The merge still occurs as it normally would -- all of the commit IDs that existed on the source branch now exist on the destination branch.
I tried this solution, and it no longer works. It appears that the fix for Atlassian BSERV-4219 (https://jira.atlassian.com/browse/BSERV-4219) has caused the server to decline the pull -requests if you push the release/target branch before you push your feature branch.
In order for Bitbucket to recognize the request as merged, I had to push the feature branch before pushing the release branch:
git merge --ff-only --squash $FEATURE_BRANCH
git commit -m "B-$BLINUM: $MESSAGE" -m" Delivery of $FEATURE_BRANCH"
git branch --force $FEATURE_BRANCH HEAD
git push --force origin $FEATURE_BRANCH
git push origin $RELEASE_BRANCH
See this SO discussion for more info:
Can you explain this a bit more?
You squash the changes on the feature branch. I assume you have checked out the target branch, which is the RELEASE_BRANCH?
Then this line which I find confusing.
git commit -m "B-$BLINUM: $MESSAGE" -m" Delivery of $FEATURE_BRANCH"
Then force push the feature branch head. But have you modified it?
Then force push the target branch. Which you have modified.
Sorry if i am being dense, but I have this requirement and want to understand.
The commands as written effectively squash-rebase the feature branch, push the feature branch, then push the target branch with the same commit.
Making the squash merge in git itself leaves no references to the original branch. You need to have the same commit on both branches for BB to recognize the branch (and pull requests) as being related to a commit on master / $RELEASE_BRANCH. So you squash merge your TASK-001 branch to master, commit the result, and push it to origin. This is effectively doing a squash-rebase from master. You then set master to point to the same commit, and push that to origin.
You are effectively setting both the master and TASK-001 branches to the same commit, but you need to push the TASK-001 reference to origin first otherwise Bitbucket will not recognize the merge as having occurred.
With the additional features Atlassian has delivered for updating merge messages, and with a few add-ons to verify our issues are present, in the correct state, and referenced in the merge message, we have stopped doing this client side, and are now using the native Bitbucket merge function.
In a world of dark-scrum, faux-scrum, and scrum-butt, the question still remains: What is scrum and how do you do it “right?” That’s the question we set out to answer. I'm Max, I've been teaching c...
Connect with like-minded Atlassian users at free events near you!Find a group
Connect with like-minded Atlassian users at free events near you!
Unfortunately there are no AUG chapters near you at the moment.Start an AUG
You're one step closer to meeting fellow Atlassian users at your local meet up. Learn more about AUGs