Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is there missing code in our Git repository and can it be solved with rebase?

We work with the Feature Branch Workflow, basically a central repository that we create branches from. When we're working on bugfixes and small patches we will create a branch off of master:

git checkout -b master_bug123 master

When we're done with our commits, we do the following to merge it back in:

git checkout master
git pull
git merge master_bug123
git branch -d master_bug123

Sometimes we have big projects that we need to all work on. For instance, making the site responsive:

git checkout -b responsive master
git push -u origin responsive

Then other members of the team can make their own feature branches like with the master:

git pull
git checkout -b responsive_fixmenu responsive

Currently, we're working on here, then to merge the changes back in for others to use:

git checkout responsive
git pull
git merge responsive_fixmenu
# possibly fix conflicts, add, commit, etc
git push -u origin responsive

Sometimes we find that code is going missing. My initial thought is that it might be down to one of us incorrectly resolving conflicts. When investigating though, I'm a bit confused. One particular file named core.js was missing a large chunk of code. In the file contained a string mb-search which I thought I could use as part of a git show and grep to see when it appeared and was removed. Using git log core.js I am given a list of commits, then I use that list to do something like git show abc1234:path/to/core.js | grep -c 'mb-search' to output how many times it appears in the file for that commit, but what that shows me is not a simple 0, 0, 0, 1, 1, 1, or even a 0, 0, 1, 1, 0 (which point it was deleted by mistake), but a quite random looking 0, 0, 1, 0, 1, 0, 0, 1, etc.

This leads me to the first part of my questions. Am I right in saying that if another user comes along and makes changes and makes a commit (let's call it abc1111), then does a git pull (merging in other pushed changes) which creates a merge commit (let's call it abc2222 - where the mb-search is merged in), then commit abc1111 will not contain the mb-search code that was later merged in with abc2222, after it has been pushed? If so, how can I reliably tell when some code was deleted?

This leads me on to rebase. Before we were using the responsive branch in the same way as the master branch, we used to just make changes directly to responsive, commit and push. At the time we were using rebase by default. At this point we were finding we had a lot of problems, as I'm sure would be expected. As beginners using git, trying to get to grips with the basics, we decided to just use merge and never rebase and we thought we were problem free. However now I'm seeing the above problems, I', wondering if the above could be fixed (or at least helped) by using rebase instead, but only in specific conditions.

I think before we were rebasing on the main responsive repository so commits were all over the place, code missing, etc, generally what you'd expect from someone who doesn't yet grasp the rebase rules properly. However, would this be a legit use of rebase, and safe?

git checkout -b responsive_somefeature responsive
# write code, make commits
git pull --rebase responsive
git checkout responsive
git merge responsive_somefeature

Am I right in saying this would base all my new work in responsive_somefeature on the HEAD of responsive, so that when I merge it back in it will be linear? Is the last merge correct, or should/could that be a rebase also?

like image 461
LeonardChallis Avatar asked Nov 06 '14 11:11

LeonardChallis


People also ask

What is the use of rebase in git?

What Does Git Rebase Do? A Git rebase changes the base of the developer's branch from one commit to another, so it looks like they have created their branch from a different commit. Internally, Git creates a new commit and applies it to the specified base.

When should you rebase?

In summary, when looking to incorporate changes from one Git branch into another: Use merge in cases where you want a set of commits to be clearly grouped together in history. Use rebase when you want to keep a linear commit history. DON'T use rebase on a public/shared branch.

When to use rebase vs merge?

Rebasing is better to streamline a complex history, you are able to change the commit history by interactive rebase. You can remove undesired commits, squash two or more commits into one or edit the commit message. Rebase will present conflicts one commit at a time whereas merge will present them all at once.

What can go wrong with rebase?

It is also very powerful, but sometimes things can go really wrong. One common issue is using git rebase when a branch is outdated and points to an old commit from master. Older branches can lead to a lot of conflicts, making rebase a nightmare.


1 Answers

Am I right in saying ...

Yes: merging a change creates a new commit with two (or more, but usually two) parents. It doesn't re-write either parent to include the other.


If so, how can I reliably tell when some code was deleted?

Not having introduced a feature isn't the same as having deleted it. The following graph following a merge:

base -> abc1111 [foo]  -> {merge} abc2222 [with foo and mb-search]
     \                         /
      \-> abc0000 [mb-search] /

Doesn't show abc1111 deleting mb-search. Looking for mb-search_ in that commit won't show it either, though. Basically, you're checking the wrong thing.


Instead, try git blame --reverse base..abc2222

--reverse

Walk history forward instead of backward. Instead of showing the revision in which a line appeared, this shows the last revision in which a line has existed. This requires a range of revision like START..END where the path to blame exists in START.

if you just want to see who deleted the line.


Oh, and your feature branch rebase workflow should probably be:

git checkout -b responsive_somefeature responsive
# write code, make commits

# update local branch
git checkout responsive
git pull

# rebase feature onto updated branch
git rebase responsive responsive_somefeature
## NB. this ^ will leave your feature branch checked out

# finally merge (this should be fast-forward since we just rebased)
git checkout responsive
git merge responsive_somefeature

where it's sensible to do the update & rebase periodically, so you're not working against a stale view of responsive

like image 140
Useless Avatar answered Nov 14 '22 21:11

Useless