Create
cancel
Showing results for 
Search instead for 
Did you mean: 
Sign up Log in

Knowing from which branch the current branch was created from

Mathieu Yargeau May 11, 2015

We are using a forking workflow. If a user, from his fork, wants to merge something into the master repository, I want to validate the source of his code.

 

For example, if he wants to merge his code in the branch 'releases/3.0.2/', I want to make sure that his branch 'Feature_x_y_z' was branched from the branch 'releases/3.0.2/'.

 

Is there a way to check from which branch the pull request's source branch was created from?

5 answers

1 accepted

18 votes
Answer accepted
Michael Heemskerk
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
May 12, 2015

In git, branches are just pointers to a commit and a commit is considered to be 'on a branch' if it's an ancestor of the commit the branch ref is currently pointing to. As such branch memberships are fluent. A commit that is only on your feature branch today, will be on master when you merge it. In about a years time, it will be 'on' all open feature branches at that time (because it's in the history leading up to those branches). If you've deleted the original feature branch it was created on, it will no longer be on that branch.

Git does not track what branch a commit was created on and does not track where a branch was branched off from. There is no information in git that you can use answer that question.

You can do a best guess by finding the 'closest' branch (smallest distance to a common ancestor), but this can easily lead to the wrong conclusion. Consider this case:

o - o - o - o - o - o <- master
  \    \
   \    o <- feature/a
    o <- feature/b

In the diagram it looks clear that feature/a and feature/b must be branched off from master, but alas.. in git's data model this is identical to:

o - o - o <- feature/a
  \    \
   \    o - o - o - o <- master
    o <- feature/b

and in this diagram, it looks like master and feature/b are branched off from feature/a

You simply cannot determine the 'parent branch' of a branch in git. If you really want it, you could consider adding meta-data to each commit (using git notes) to track on what branch it was created. With that information, you could answer the question. But it's a cumbersome process that is hard/inconvenient to enforce.

 

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 14, 2015

Agree that that's a great answer, but... it doesn't seem like such a bone-headed question to me that there can't be an answer. I see lots of companies that want to manage the flow of change through their branches. Is there a better way of accomplishing this?

Like # people like this
Tim Crall
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 14, 2015

I know there's a plugin that will show gitview diagrams so that the master, dev, etc, branches are displayed as they really were - I assume it must do some version of adding the branch-created-on info into the commit metadata.

Vince Panuccio July 26, 2017

gitk can determine correctly, the parent branch of a branch. So there must be a way. I'm looking for it :)

mdalikazi October 24, 2017

How do software like SourceTree show the visual info then? They must be getting this kind of data from somewhere even though it might be complicated.

Like # people like this
timhoustontx August 28, 2018

I would like to be able to see this and more.

In a pull request that merges changes, I would like to be able to see where those changes are coming from before it is approved.

(Looking at output from gitk, I think the info is there about where a branch comes from.)

Like Deleted user likes this
Kumail Raza October 26, 2018

how can i check in local?

2 votes
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 11, 2015

As Balazs says... this is a much harder question than you might think. http://stackoverflow.com/a/3162929/1018918 has some good info.

In that answer the author substitutes two better questions, which you could implement using the Stash API. Is the context for this a mergecheck plugin or a pre-receive hook or something?

You might be able to just check that all the commits in the PR (given a source ref and target ref) are on the PR branch.... I think that may be sufficient.

Update:

Given:

image2015-5-12 20:20:4.png

When I create a PR from feat1 to releases/3.0.2, it shows me two commits. When I change the target to master, it shows me 3 commits. 

You can get this info from com.atlassian.stash.commit.CommitService#getCommitsBetween, where the CommitsBetweenRequest has a ctor for a PR, or from PullRequestService if you have an already created PR.

If these are the same commits as those between releases/3.0.2 and the fromRef in my PR, then that's where I branched from... although I may have intermediate branches on the way, but I'm not sure that matters.

However, if master was pointing to the same commit as releases/3.0.2, then it would be true for master.

I'm interested in the answer to this too, and I wonder if there is not a much better way. I hate to mention people but I think a good person for this question is @Michael Heemskerk.

 

Mathieu Yargeau May 12, 2015

I think I did not understand what you meant. Check if the commits in the PR are on the PR branch? You mean check if the commits in the PR (which are from the 'Feature_x_y_z' branch) are in the 'releases/3.0.2/' branch? They won't be. The commits in the PR are only in the feature branch.

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 12, 2015

When you create a PR it works out what commits need to be merged from source to target branch. If that list are all on the feature branch, I think that's what you want.

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 12, 2015

i told you it was tricky... answer updated.

1 vote
Balázs Szakmáry
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 11, 2015

There is no way to check this built into Stash. You can use git log to figure this out, but it gets rather complicated.

0 votes
Nitesh Gour September 5, 2019

Great!

0 votes
JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 26, 2015

@Michael Heemskerk - thanks for your full answer.

Can we consider another case? Let's say we have a pre-commit hook, whereby we want to examine each commit that is pushed, imagine we want to check that it's signed or the commit message is greater than 2 characters or something. That sounds like a possible requirement.

In the case of a new branch feature/a being added with a commit:

o - o - o - o - o - o <- master
       \
        o <- feature/a

The refChange we get will look like [ 00000000 .. A ] , assuming A is the sha1 for the tip of feature/a.

Using commitService to get the new commits we will get all the ancestors of feature/a too, which is obviously not acceptable. 

We can get the commits on feature/a using:

git rev-list feature/a ^master ^refs/heads/branch1 ... ^refs/heads/branchN

ie using a CommitsBetweenRequest and excluding every other branch than feature/a. This works AFAICT but seems "wrong". This is the approach used here: http://engineering.onlive.com/2014/04/18/why-post-receive-git-hooks-are-broken/

I get that under the covers Stash is using standard git hooks, and it passes on all the information the hook receives, but I wonder if there is scope for Stash being more clever and providing information about the list of commits.

Presumably this is possible, as at some point git goes through the pushed commits and squirts them on to the correct parent. If we had that parent for each RefChange life would be simple.

There must be a hook somewhere that examines each commit, and works for the case of newly-added branches - does anyone know of one?

 

 

 

 

 

Michael Heemskerk
Atlassian Team
Atlassian Team members are employees working across the company in a wide variety of roles.
May 26, 2015

bq. Let's say we have a pre-commit hook, ... Nitpicking, but to be exact, it's pre-receive hook. A pre-commit hook runs in your local repo when you do {{git commit}} bq. I get that under the covers Stash is using standard git hooks, and it passes on all the information the hook receives, but I wonder if there is scope for Stash being more clever and providing information about the list of commits. As you said, Stash is using 'plain' git hooks. We do have some smarts to detect which commits have been added, but those smarts are applied at a later stage (during indexing) and can't be used here. Given that you get a list of {{RefChange}}, it's not too hard to retrieve all commits that are about to be added by this push. Remember that when the pre-receive-hook is called, the refs haven't been updated yet. They're still pointing to the old values. This means that the following git command should only return the commits that are about to be added: {code} git rev-list <sha1> <sha2> <sha3> --not --all {code} where {{<sha1>}}, {{sha2}} and {{sha3}} are the {{RefChange.getToHash()}} hashes for the provided {{RefChange}}s. The {{--not --all}} means that all current refs (branches and tags) are excluded. So, this command reads as: 'give me all commits that are reachable from sha1, sha2 or sha3 and are not reachable from any current ref'

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
May 26, 2015

Thank you... do you know how to do that in a post-receive hook where the refs have already been updated?

JamieA
Rising Star
Rising Star
Rising Stars are recognized for providing high-quality answers to other users. Rising Stars receive a certificate of achievement and are on the path to becoming Community Leaders.
June 1, 2015

Perhaps there is not a good answer to this question, as hipchat notifications from stash seem to suffer from this problem: https://jira.atlassian.com/browse/STASH-7455

Suggest an answer

Log in or Sign up to answer
TAGS
AUG Leaders

Atlassian Community Events