Gerrit always rebase before submit patchset to avoid a merge commit - merge

I found that when clicking "Submit Patch Set" in the Gerrit web interface, it'll either simply add a commit to that branch, or create a merge commit if another commit was submitted just before.
Example that creates 2 commit: The actual commit and a merge commit:
User submits patchset A depending on commit O
User submits patchset B depending on commit O
Submit Patch Set A
Submit Patch Set B --> Creates merge commit between O -> A and O -> B
There is a "Rebase Change" button which is great but it means that to submit a patch set everyone should always do:
Click Rebase Change
Click Submit Change Set
The only reason I see a merge commit useful is to keep dates of the commits (but I do understand why it is required without a rebase).
Isn't there an automatic rebase or at least a check to avoid generating an undesired merge commit?

Yes. Change the Submit Action for your project(s) to Cherry Pick. This will do roughly the same as rebasing when the submit button is pressed. It will keep the clean history you are looking for with no merge commits when submitting changes.

You can change the default submit type of the project by visiting the project settings page and choosing "Rebase if necessary" instead of "Merge if necessary".
For the complete documentation of Submit Types, see: https://gerrit-review.googlesource.com/Documentation/config-project-config.html#submit-type
The method Gerrit uses to submit a change to a project can be modified
by any project owner through the project console, Projects > List >
my/project. In general, a submitted change is only merged if all its
dependencies are also submitted, with exceptions documented below. The
following submit types are supported:
Inherit
This is the default for new projects, unless overridden by a global defaultSubmitType option.
Inherit the submit type from the parent project. In All-Projects, this is equivalent to Merge If Necessary.
Fast Forward Only
With this method Gerrit does not create merge commits on submitting a change. Merge commits may still be submitted, but they
must be created on the client prior to uploading to Gerrit for review.
To submit a change, the change must be a strict superset of the destination branch. That is, the change must already contain the tip
of the destination branch at submit time.
Merge If Necessary
If the change being submitted is a strict superset of the destination branch, then the branch is fast-forwarded to the change.
If not, then a merge commit is automatically created. This is
identical to the classical git merge behavior, or git merge --ff.
Always Merge
Always produce a merge commit, even if the change is a strict superset of the destination branch. This is identical to the behavior
of git merge --no-ff, and may be useful if the project needs to follow
submits with git log --first-parent.
Cherry Pick
Always cherry pick the patch set, ignoring the parent lineage and instead creating a brand new commit on top of the current branch head.
When cherry picking a change, Gerrit automatically appends onto the end of the commit message a short summary of the change’s
approvals, and a URL link back to the change on the web. The committer
header is also set to the submitter, while the author header retains
the original patch set author.
Note that Gerrit ignores dependencies between changes when using this submit type unless change.submitWholeTopic is enabled and
depending changes share the same topic. So generally submitters must
remember to submit changes in the right order when using this submit
type. If all you want is extra information in the commit message,
consider using the Rebase Always submit strategy.
Rebase If Necessary
If the change being submitted is a strict superset of the destination branch, then the branch is fast-forwarded to the change.
If not, then the change is automatically rebased and then the branch
is fast-forwarded to the change.
When Gerrit tries to do a merge, by default the merge will only succeed if there is no path conflict. A path conflict occurs when the
same file has also been changed on the other side of the merge.
Rebase Always
Basically, the same as Rebase If Necessary, but it creates a new patchset even if fast forward is possible AND like Cherry Pick it
ensures footers such as Change-Id, Reviewed-On, and others are present
in resulting commit that is merged.
Thus, Rebase Always can be considered similar to Cherry Pick, but with the important distinction that Rebase Always does not ignore
dependencies.

Related

Revert merge in pending changes but keep local changes (Azure Devops)

I just accidentally merged to a branch that I had 40+ local changes on - so now my changes and the merge are together, which I definitely do not want, with a lot of the files having edit & merge changes. I want to completely revert out the merge, is there a way to do this? If not, I'm in trouble.
I haven't checked anything in, I just only want to keep my local changes that I made.
If you merge to a branch via pull request in Azure Devops, then you can revert the completed pull request directly.
In Target branch, select the branch where you want to undo the pull request changes.
In Topic branch name, select a new branch where the reverted changes are created, then select Revert.
Select Create pull request to merge the newly created branch in a second pull request to complete the revert. For details ,please refer to this document.
If I ignore something, you could attach detailed steps or flow for this issue , this would be much easier for me to understand and reply.
I agree with Leo BL. You can try to copy your current project folder into temporary folder. Then checkout the merge source branch and compare it with temporary folder by some diff/merge tool. However, that maybe difficult to cut your changes if they were in the same files with the merge operation.
Just a quick hint: Basically, this is a git question. So maybe you should consider giving it the git tag aswell, so you can reach a greater audience.
Regarding your question: What means local change? Is the stuff not committed at all? What does git status show?
Assuming the changes are not committed, you could use git stash. I recommend this SO question:
Cancel git merge but keep local changes
I would try it this way:
1. Backup the directory (so you have a backup if something goes wrong)
2. Stash your changes
3. Revert the merge
4. Load the stashed changes
—> You should be fine
sorry but you are in trouble. After the merge the files are replaced

If squashing never alters committers, why does Github's squash-and-merge button update the committer?

In the spirit of testing the "there are no dumb questions" theory, why does Github's squash-and-merge strategy update the committer after merging a pull request?
That is, suppose I author a pull request in my fork of a project. Suppose it has two commits in it. Suppose I ask the project maintainer to now merge my pull request to master of the upstream project.
Suppose she chooses the squash-and-merge strategy so that there will be one commit at the end.
Suppose further that the merge can be accomplished via a fast-forward, i.e. as simple as possible a case as I can think of. (Fast-forward merges should just update the branch pointer, which seems to me like it would leave the commit completely unchanged.)
Why is it, then, that the latest commit on master after the squash and merge operation features me as the author (I understand that part) but the maintainer as the committer? Isn't that an alteration of a commit, and doesn't squashing and fast-forward merging ensure that commits are not altered?
Is Github silently doing the equivalent of something like git amend under the covers?
Isn't that an alteration of a commit
More than an alteration: a creation of a new commit, which reflect the changes of your two commits.
And your two commits are no longer referenced by the main repo: it references only the squashed commit.
That new commit has still you as an author, but is committed by the maintainer.

Git uncomitted file confirmation when switching branches

I am using the git plugin for eclipse and I have noticed a problem with it and hoping this is a simple configuration change. Can anyone help?
When switching branches, the uncommitted changes are being merged across onto the newly checked out branch (only in certain circumstances). It seems as if this happens every time when it is "safe" to do so. The way to recreate is:
Create feature branch "branch1" from remote repository
Create feature branch "branch2" from same remote repository
Make changes on "branch2" and don't commit changes.
Switch to "branch1"
a. No confirmation message is shown.
b. The uncommitted changes from "branch2" are merged onto "branch1"
I want to be able to force the commit message to appear (just like it does using git-bash). Is this possible?
To my understanding, this behavior is intended by EGit: a checkout is performed as long as the files to be checked out do not collide with the working directory. And uncommitted changes are left as they are.
If you think EGit should offer a different strategy of handling uncommitted changes I suggest to open an enhancement request: https://eclipse.org/egit/support/
In the meanwhile, you may want to (manually) stash uncommitted changes prior to switching branches. That's what I see most people do in this situation.

Gerrit: working with multiple branches & propagating changes

I'm trying to identify the proper way of working with multiple branches on Gerrit that would match our workflow.
The way we work with branches right now is: we have master & feature branch. Master is the branch we want to polish and make it ready for release, while feature is obviously a field of intensive work. Now, in our particular case whenever somebody works on a bug fix, they:
create a change targeted for master branch
cherry pick it to the feature branch targeted change
once gerrit code review completes, submit both changes.
now the way i understand cherry-pick, it selects individual commit and merges it to the current change. if that is the case, i would expect to have no merge conflicts in the end, and indeed this workflow works perfectly with just GIT. Gerrit, however, most likely due to its nature (branches are not merged remotely the way these are locally and get a different sha tag) lists a tremendous number of conflicting files in the end.
Now, I resolved all these issues by applying merge strategy (ours on feature, theirs on master), but it does not feel right: if anything was not propagated, it just got discarded.
My question is: is there a safe workflow, similar to the above one, that would in the end produce a clean merge with gerrit?
I would say that it's better, in this case, to merge than to cherry pick.
A cherry pick adds the same changes but not the same commit. So while the source is the same on a cherry pick and merge the git tree is different. When the tree is different and you later do a merge git will think that the commit you previously cherry picked is missing and try to merge that change as well, even if the actual code is already there. That's probably why you get a lot of conflicts.
I would propose another way of working.
When you do normal work you develop on feature and push to Gerrit as normal.
When you do a patch (ie bug fix) on the stable production environment you do that directly on master (or local branches if you like but not on feature)
When the patch as been approved in Gerrit it get's merged into the real master and you can make a pull request to get that change to your local copy. Your version of master is now the same as Gerrits master
Now you would merge all new changes on master into feature. Make sure you do a rebase so that the patch ends up before anything you've already done on feature
Once it's time to deploy all new features you can merge feature into master, push to Gerrit (if you have permissions you can by pass gerrit by pushing directly to master instead of refs/for/master as these changes are already reviewed)
Once all changes are on Gerrits master you do a pull on your master and a merge into feature with rebase making feature a clean branch to work on. It's of course totally valid to have a new feature each release. Both work fine.
I'm a little confused, as this flow should work just fine. If other users submit changes before your bug fix is reviewed/verified/submitted, that could result in merge conflicts, but that should be rare.
If you:
Fix a bug on master
Push to review (creating change A in gerrit)
cherry-pick change A on top of the feature branch (resolving any conflicts from master to feature)
Push the cherry-picked change to review (creating change B)
Review/verify/submit changes A & B
Everything will work fine. The only way for merge conflicts to occur is if other users upload and submit changes between steps 1 and 5. Are you seeing different behavior? Can you provide more details?

Merging of branch to trunk in SVN using Eclipse

I am looking forward to merge my code which I developed in a branch of SVN to the trunk. I am using Eclipse and I have been using Team->Commit to commit my updates to the SVN. But I haven't done a merge before. Please help me with this.
First of all make sure you are up to date. Update your working copy of the target branch, ie. where you are merging into. In this example we're working on the trunk of "core" and we want to grab the changes that have happened in the maintenance branch and merge them.
Resolve any conflicts. There should be no conflicts at this stage between the working copy and the repository.
Select the SVN merge option on the working copy. In Eclipse this is going to be found under the "Team" menu and called "Merge Branch".
SVN: Merging in Eclipse
Change the From URL to the specific branch you want to be merged into your working copy. In this example we're looking for the p400 maintenance branch (./core/branches/p400).
Change the From Revision to the last revision that was merged into the target branch. Essentially you don't want to keep merging the whole branch history, you just want to include those changes since the last time you merged. There is no easy way to determine the last merge point at this time in Subversion. You have to review your message log and look for the last commit that talks about merging. If you are disciplined about the commit messages you use for merging this should be easy (see below). Make a note of what that revision is -- you'll need this later when you commit your changes.
SVN: Merge with Eclipse
Change the To Revision to the latest (i.e. head). Make a note of what that revision is -- you'll need this later when you commit your changes.
Click Merge and wait. Depending on how big the differences are this may be quick or Eclipse my just fall over. If you have such an enormous change that you can't get it done in Eclipse you may need to make the range of revisions you are merging smaller. Or you may even have to skip certain revisions and do them manually if they are massive. We've had this problem from time to time when updating large third-party libraries. The vast majority of the time you will be fine.
Review changes and resolve conflicts. Once the merge is complete, look through the changes made to your working copy and make sure you address any conflicts you find.
Once all the changes have been resolved in the target working copy, check them in with a single commit. The reason you're not doing lots of commits is that these are changes that should have been documented in the branch from which you merged. The commit message needs to be in a specific format that details the merge and is easy to find in the future. We use the following format, but you can use anything that works for you -- as long as you stick to it.
Merging [source] to [target]; [repository]. Merge rev [start]:[end]
Enjoy!
In eclipse we have an option to merge. Right click the project , you will see "Team" option and on clicking it you will see merge option. There are three different options you can see in the merge.
To successfully merge the changes from the branch to the trunk, we need to switch the local workspace to the trunk (but make sure all the changes are committed to the branch before that). Once we do that we can use merge option and select "2 URLs" option. I put url for trunk as url 1 and the branch I wanted to merge as url 2. I could see all the incoming changes I selected "OK". All the changes are in my local now (at this point my workspace is linked to the trunk). Then I committed my changes to the trunk and hence merge from branch to the trunk was successful.
I would like to add for Point 8 .Review changes and resolve conflicts. ---
When working on conflicts manually- when you do copy from right to left on chunks of code - Be careful
Sometimes chunk of code gets added, sometimes it properly replaces the chunk.
Make sure there is no duplicate chunk of code.
Also, this is helpful-- What is the proper way to do a Subversion merge in Eclipse?