Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

confused about creating nested branches in git

Tags:

git

branch

nested

I just started using git and started collaborating with other developers on same code. I have worked a little with SVN before but never had to collaborate with other people on my codebase. Now with collaborators working on same code, I need an efficient workflow. While searching for such, I found this, and it seems like a good workflow for our requirement.

My repository resides in a local machine. I created the repository with git init --bare. I added the initial codes to master and pushed it. Then I added a "develop" branch using git branch develop; git push -u origin develop.

Now I want to create feature branches from "develop", and I want these feature branches to be accessible by all collaborators. I wish to have a nested structure, something like this

origin/master
origin/develop
origin/develop/newFeature
origin/develop/anotherFeature
etc.

so that when a collaborator types in git branch -a he/she will immediately know the "newFeature" is in the "develop" line, and decides what to do.

So after some trial and error, this is what I did:

git clone file:///path/to/repo --branch develop
git checkout -b newFeature develop
EDIT some files
git add .
git commit
git push origin newFeature

Now this "newFeature" is available for all collaborator to clone. git branch -a gives me

  develop
* newFeature
  remotes/origin/HEAD -> origin/master
  remotes/origin/develop
  remotes/origin/master
  remotes/origin/newFeature

So is the "newFeature" really part of the "develop" branch? Or is it now branch by itself? Once I clone the "newFeature", how do I check whether it is the develop line? This may potentially be confusing as I may end up having a branch named "newFeature" in master in due time!

My understanding of how git works is definitely inadequate. Therefore, if anyone can point me to right direction, that will be great!

TIA,

like image 552
Somesh Avatar asked Mar 01 '15 05:03

Somesh


People also ask

Can we create nested branch in git?

This means you can have the names grouped together: just create the names as develop/anotherFeature and develop/newFeature originally. The slash is, in this case, merely a part of the name. The problem here is that git originally implemented1 these branch names by putting them in directories containing files.

How do I make multiple branches in git?

Git offers a feature referred to as a worktree, and what it does is allow you to have multiple branches running at the same time. It does this by creating a new directory for you with a copy of your git repository that is synced between the two directories where they are stored.

Should I create new branch every time?

It's a good practice to create a new branch for every new bit of work you start doing, even if it's a very small one. It's especially useful to create a new branch for every new feature you start working on. Branches are of course disposable, you can always remove them.

Can I work on 2 branches simultaneously?

You can have many branches in your repository, but only one of these will be "checked out" as the working-tree so that you can work on it and make changes. git worktree adds the concept of additional working trees. This means you can have two (or more) branches checked-out at once.


1 Answers

TL;DR version: just git checkout -b develop/feature initially (you'll need to not have a branch named develop for this to work though!).


Branches don't really "nest" for a ridiculously simple reason: a branch name (like newFeature) merely stands in for some commit-ID, i.e., some SHA-1 "true name" of some commit.

(In this respect, a branch name is the same as a tag, like "v2.3".)

The thing that makes (local) branch names special—what makes them different from any other reference—is that "git checkout" will let you get "on a branch" by writing the name of the branch in git's HEAD file, and, once you have done that, making a new commit will automatically update the branch-name so that it points to the new commit you just made.

(Remote branch names can't be gotten "on" this way, but will also change their target SHA-1 as needed. I mention this only because the next paragraph mentions "remote branches" or "remote-tracking branches", which you'll see in git branch -r output.)

Branch names are, however, sorted by git branch --list (after sorting by "kind", i.e., grouping all local branches together first, then all remote branches). This means you can have the names grouped together: just create the names as develop/anotherFeature and develop/newFeature originally. The slash is, in this case, merely a part of the name.

The problem here is that git originally implemented1 these branch names by putting them in directories containing files. On the systems that support git, you can't have a directory named develop and a file named develop at the same time.2 So if you have a branch named develop, git may have created a file (.git/refs/heads/develop, specifically), which then prevents it from creating a directory (.git/refs/heads/develop, again) containing the file (newFeature) containing the SHA-1 of the commit that the branch currently identifies.


1While git now also uses a flat file (.git/packed-refs) to store branch-to-SHA-1 mappings, it still also uses directories of files, and must make sure that you don't create a name that must serve as both directory and file.

2Personally I think it makes sense for a file system name entity to work as both directory and file: this would be a way to, for instance, store all the ELF sections of an executable as files within the directory that is the executable program, or handle the things that MacOS does for app bundles. But this violates all kinds of rules for the way things must work in POSIX, so it would require a major redesign of the file system name space(s), and would be more suitable as a follow-on to Plan 9 (for instance) than as a Unix-ish variant.

like image 109
torek Avatar answered Oct 01 '22 12:10

torek