What does the `Rebase and merge` merge strategy do on Bitbucket Server? - git-rebase

I was exploring the possible merge strategies on Bitbucket Server and one strategy caught my eye: "Rebase and merge" rebase + merge --no-ff
I understand that most of the debate about merge strategies revolves around rebase vs merge. This merge strategy seems to be rebase and merge. Is this correct? What advantages would this bring as opposed to only rebase or only merge?

The "rebase and merge" strategy is usually what people mean by "rebase". It just also indicates what happens next. When you use --no-ff, it makes a merge commit. Without it, you get a fast-forward so both refs would point to the same commit and it hides the fact that you had branched at all.
Merge B onto A:
A *---* A *---*---*
\ merge -> \ /
B *---* B *---*
Rebase B onto A:
A *---* A *---*
\ rebase -> \
B *---* B *---*
Rebase and merge (--no-ff) B onto A:
A *---* A *---* A *---*-------*
\ rebase -> \ merge -> \ /
B *---* B *---* --no-ff B *---*
Rebase and merge (--ff) B onto A:
A *---* A *---* A,B *---*---*---*
\ rebase -> \ merge ->
B *---* B *---* --ff

Bitbucket Server documentation says this for Rebase, merge (rebase + merge --no-ff) AND Rebase, fast-forward (rebase + merge --ff-only) merge strategies.
"The PR branch is not modified by this operation"
As per this statement, in your example the commitSHA for the commits in branch B would remain unchanged. Bitbucket would assign new commitSHA for the same commits when applied in branch A.

Related

I have 2 git branches develop and master but mistakenly some of the code is directly checked-in to master

Some of the code is directly pushed to master which is not in develop branch
Also their is some code which is checked-in to develop but not merged to master yet
What would be the best possible way of syncing both branches so that both will have the same code
Typically you would view the remote master branch as the ultimate authority regarding the state of your product. Under this assumption, you might first update develop with the latest changes coming from master, and then push that updated develop branch back to master. Here is one way:
git fetch origin
git checkout develop
git merge origin/master
# resolve any merge conflicts, etc.
git push origin develop
Then, you would look to merge develop into master. If you are using something like GitHub, this might happen via a pull request. So, you would create a pull request from develop pointing back to master as the target branch. If you wanted to do the merge locally, then you could try:
git checkout master
git merge develop
git push origin master
But most large software projects use a repo like GitHub or Bitbucket to prevent anyone from directly updating master in this way.
If I understand, normally you commit to develop and then merge develop into master. master is always behind develop. Something like so.
A - B - C - D [master]
\
E - F - G [develop]
You can use git log --decorate --graph to get this sort of view of your repository.
But somebody made commits directly to master, H - I below, and you have this situation.
A - B - C - D - H - I [master]
\
E - F - G [develop]
Instead you want this.
A - B - C - D [master]
\
E - F - G - H - I [develop]
Again, we're here.
A - B - C - D - H - I [master]
\
E - F - G [develop]
You can use git cherry-pick to copy H - I on top of develop.
git checkout develop
git cherry-pick H I
A - B - C - D - H - I [master]
\
E - F - G - H1 - I1 [develop]
Then move master back to D.
git checkout master
git reset --hard D
A - B - C - D [master]
\
E - F - G - H1 - I1 [develop]
Push both branches with --force.

git branch -vv seems to contradict itself when trying to work out whether by how many commits it is ahead/behind when tracking with remote branches

$ git status
On branch CurrAsOf18Jan2018
Your branch is up to date with 'remotes/bitbucketFrmWin/master'.
nothing to commit, working tree clean
But I know that my bitbucket repo is ahead by a couple of commits Ques:Do I have to always do a git fetch --all so that my local git can be sure - I thought I was tracking my remote repo bitbucketFrmWin - Anyways I do the following .....
$ git fetch --all
Fetching bitbucketFrmWin
From https://bitbucket.org/FreeFries/simplcontactsvcf
50d1fc6..d79d834 master -> bitbucketFrmWin/master
Good now my local repo can check against the fetched remotes whether it is ahead/behind
$ git status
On branch CurrAsOf18Jan2018
Your branch is behind 'remotes/bitbucketFrmWin/master' by 5 commits, and can be fast-forwarded.
nothing to commit, working tree clean
Okay I am happy with that it is what I thought
$ git branch -vv
* CurrAsOf18Jan2018 50d1fc6 [remotes/bitbucketFrmWin/master: behind 5] Pedantic but done - gitNotes.txt
bitbucketFrmWin/master 58470cd [CurrAsOf18Jan2018: behind 7] This is really crazy - Spent more than a week - Singleton still gives null pointer inJdbcExample2
Now this is what throws me [CurrAsOf18Jan2018: behind 7] (see last output line above) ... It should have said ahead by 5 - after all it is comparing the same remote repo branch. What am I missing in my understanding here ?
$ git merge --no-commit --ff-only d79d834
Updating 50d1fc6..d79d834
Fast-forward
.gitignore | 2 ++
gitNotesUpgradeInstall.txt | 38 ++++++++++++++++++++++++++++++++++++++
sqliteData/testtestdb.sqlite3 | Bin 278528 -> 0 bytes
3 files changed, 40 insertions(+)
create mode 100644 gitNotesUpgradeInstall.txt
delete mode 100644 sqliteData/testtestdb.sqlite3
I go ahead with the git fetch it fast-forward's my local branch - I tell it not to commit - but ignores my request and commits anyways - Why ?
Also my bitbucket branch master is actually already ahead at commit d79d834 but "git branch -vv" above does not show that commit sha signature in it's listing despite the fetch - Why ?
$ git status
On branch CurrAsOf18Jan2018
Your branch is up to date with 'remotes/bitbucketFrmWin/master'.
nothing to commit, working tree clean
Nevertheless git status knows now that it has caught up with my remote branch above and is happy
If someone can throw light on the questions posed above as to whether these are bugs or misunderstanding in the git work flow above - I would be grateful. Thanks.
I go ahead with the git fetch it fast-forward's my local branch - I tell it not to commit - but ignores my request and commits anyways - Why ?
Because there is no commit to be made: it does not make any commit: it just fast-forward your branch HEAD to the remote one.
And bitbucketFrmWin/master is a local branch, not remote one!
Its name is poorly chosen, as it matches the one of a remote: remotes/bitbucketFrmWin/master.
But being local, it is not surprising it too is behind its remote counterpart (which just got updated with git fetch bitbucketFrmWin).
If you want to see your remote as well as local ones, type:
git branch -avv
You will see a remotes/bitbucketFrmWin/master branch as well.

what will happen when merge, if both master and branch has changed in bitbucket

I have a branch from master in my local machine. I know how to merge something to master repo. but question is this.
Think some other developer has changed the master repository by pushing changes to it and at the same time I'm going to merge changes to the master repository from by branch.
What will happen at this situation.
What should I do in this type of situation. I tried to do following from my branch.
added my changes with -> git add *
then committed with -> git commit -m "my commit"
then push to my branch with -> git push -u origin my_branch_name
then changed the repository to master with -> git checkout master
then merged branch to master with -> git merge my_branch_name
up to this stage it was successful. then I tried to push with following command (before few minutes ago, another developer has pushed to master)
git push origin master
then it says followings.
! [rejected] master -> master (fetch first)
error: failed to push some refs to 'git#bitbucket.org:abcdef/cups.git'
hint: Updates were rejected because the remote contains work that you do
hint: not have locally. This is usually caused by another repository pushing
hint: to the same ref. You may want to first integrate the remote changes
hint: (e.g., 'git pull ...') before pushing again.
hint: See the 'Note about fast-forwards' in 'git push --help' for details.
at this stage, what should I do.
should I get a pull after the merged step and then push (in this stage if i get a pull, what will happen.) or
do I have to do something like git stash, then push and something like that.
hope your help with this. thank your very much.
You need to Pull remote/master (to get all remote changes), then you are able to push your local changes.
Say, When you pulled remote/master there were 2 commits (A, B)
remote/master: A -> B
local/master: A -> B
Then other developer pushed a commit P to master
remote/master: A -> B -> P
local/master: A -> B
Then you've committed X in your branch (say, feature)
remote/master: A -> B -> P
local/master: A -> B
local/feature: A -> B -> X
Now Merged your feature with local/master
remote/master: A -> B -> P
local/master: A -> B -> X
local/feature: A -> B -> X
Now you've to pull your remote/master to fetch all commits of remote/master into local/master.
remote/master: A -> B -> P
local/master: A -> B -> P -> X # now local/master has P (sync with remote/master)
local/feature: A -> B -> X
Push your local/master to remote
remote/master: A -> B -> P -> X
local/master: A -> B -> P -> X
local/feature: A -> B -> X
You need to retrieve the work that has been pushed by the other person and integrate it locally before being able to push.
You can either perform a "git pull" directly, or better, perform a "git fetch", followed by either a "git merge" or a "git rebase".
The advantage of the fetch is to allow you to see what commit has been pushed by the other user. You can then decide to do a merge or a rebase. The rebase has the advantage of resulting in a "cleaner" tree.
If you have some ongoing work (files that you have staged), you need to decide if you want to integrate that in your next push. You then need to decide to discard them, stash them or integrate them to your next commit.

Github throttled push

I want to push changed work from local machine to remote GitHub account.
How can I use github to push only 10-15mb per day and not to attempt entire 1GB, as otherwise will go out of limits?
It can keep running for 10 days or I can restart it each day to upload a 10-15mb chunk.
You can try and git push up to a certain commit.
For example, you have 5 commits A>B>C>D>E pending (for simplicity, ABCDE are commit hashes), and you want to push up to commit "C". The following will then push A, B, and C to origin/master.
git push origin C:master
But if commit D is to big (meaning if, after doing git push origin C:master, a git push origin D:master fails), then you would need to split D (git rebase -i)

Find all commits in a particular branch in GIT

This might be a repeated question but i didn't find exact answers.
Lets say i have 2 branches br1 and br2 with 3 commits each.
br1
commit a
commit b
commit c
br2
commit d
commit e
commit f
When i merge from br2 to br1, git log on br1 show commits a,b,c,d,e,f.
Lets say i have 2 branches br1 and br2 with 3 commits each.
br1 after merge with br2
commit a
commit b
commit c
commit d
commit e
commit f
Is there a way to filter commits that were created on br1 alone? (I have tried git log br1..br2 but is there any other method?)
If the merge was Fast-forward or Automerge, will GIT record any commit for the merge? (i see commit when there is a conflict but not in an automerge)
A branch is just a pointer to a specific commit. So you can't find out from what branch a certain commit came from.
When doing a fast-forward, the only thing that changes is that the commit a certain branch points to is switched, so no extra commit will be recorded. If you do want an extra commit to be recorded, use git merge --no-ff.
I'm not certain why this is important to know, but if it is, then you could create a new branch from br1 and use that branch to merge br2. Then br1 and br2 are unchanged, and you can tell which one includes which changes, while you also have a merge branch containing both sets of changes.
br1
a
b
c
br2
d
e
f
mbr1_2
a
b
c
d
e
f
The problem with git log br1..br2 is that it will try to suppress the commits the commits that are part of br1, but all the commits are part of br1 now, so nothing will show.
What you can do is find the commit right before the merge of br2; git log br1^..br2, but that would only work only if br1 has not moved forward.
In general the best way is to find out the relevant merge, and show the commits that were merged:
git log merge^1..merge^2