Ashwin Karki
Ashwin Karki

Reputation: 269

Git branches are not listed when runned the git command

I made a new repository in github and named it as try.The folder is empty,and i made two new branches :

ashwin
anil

When I try to list these branches,it is not listing me the branches.The image contains the commands i runned:

enter image description here

The folder try is completely empty with .git folder

Upvotes: 1

Views: 1346

Answers (1)

torek
torek

Reputation: 487865

I made a new repository ... and i made two new branches

The thing is, you did not make two new branches. You simply switched the name of the branch that you were on, twice, without creating anything. This requires some fancy explaining.

A new repository is, initially, completely and totally empty.1 It has no branches and no commits. Nevertheless, you are on branch master, as git status will tell you. There is something fundamentally weird about this.

The problem here is that the way Git handles branch names like master is that for them to exist, they must contain the raw hash ID of some existing, valid Git commit. If your Git repository has one commit, or two, or thousands, you can have branch names. Even if you have only one commit, your Git repository can now have ten thousand branch names. But if you have no commits, your Git repository cannot have any branch names, because with no commits, there are no valid commit hash IDs.

The hash ID of each commit springs into being at the time you—or whoever is creating the commit—create the commit. Until that moment, its hash ID does not exist. After that, its unique-to-that-one-commit hash ID exists. It remains valid for as long as that commit itself also exists. And, now that this commit hash ID exists, you can store this hash ID in any number of branch names. You can now create as many branch names as you like, all of which can contain this hash ID, or of course any other valid, existing commit hash ID.

Git needs to know which branch name to create, when you create that first commit. This peculiar state of being on a branch that doesn't actually exist yet is there so that the first commit you create will create the branch name for you.2 That is, your initial, totally-empty repository has no commits and no branches can exist. Then you use git commit to create the very first commit. Now some branches can exist. One will exist, because git commit will create it. The name that git commit will create is the name you told Git to store as your current branch.

When you're in this funny state, git checkout -b asdf doesn't create branch asdf, it just changes the name of the non-existent branch that you're on. Later—after one or more commits do exist—running git checkout -b does create additional branches. This all might make more sense if git checkout -b refused to do anything in this funny state. You can also use git checkout --orphan when you are in this funny state, so there would be no loss of functionality. But git checkout --orphan is an option that was new in Git 1.7.2, so git checkout -b has to continue to work to be backwards-compatible with older versions.


1When using GitHub's "create new repository" feature, they offer you the ability to immediately add one commit containing a README file, and optionally, .gitignore and/or LICENSE files. When using the git init command to create a new repository, it is empty: you must add this first commit yourself. It's clear that whichever method you used, you did not have any commits yet.

2That branch name is stored in the file .git/HEAD. You're not supposed to use this directly, but it helps, I think, to actually look at what's in that file. Don't edit the file yourself directly; just take a quick peek at it to get an idea of how Git uses it. Always use Git commands to change its contents, so that you don't break things. If you get the .git/HEAD file wrong, Git will actually stop believing that the repository is a repository at all. Note also that if you start using git worktree add, that HEAD file stops being the only HEAD, and you can't rely on it after all—but it's still OK to look in the .git directory now and then, as long as you remember that Git itself reserves the right to change how everything works internally. Git only promises that all the user commands will still work, in the next version of Git.


A visual guide might help

Consider the case of a new, totally-empty repository with no commits. You write some files, run git add on them, and run git commit, and now the first commit does exist. It gets a new and unique hash ID—we can't predict what it will be,3 we only know that it will be new and unique—but let's just call it commit A, and draw it like this:

A

Git will write the actual hash ID, which is probably more like 7c20df84bd21ec0215358381844274fa10515017, into whatever branch name you choose, but if you haven't chosen one yourself, the default name will be master. We then say that the name master points to this commit, and we can draw it:

A   <-- master

The special name HEAD, written in all capitals, contains the name of the branch; we say that HEAD is attached to this branch name, and we can draw that too:

A   <-- master (HEAD)

You can find the actual hash ID of this commit using git rev-parse:

git rev-parse HEAD

or:

git rev-parse master

will print out the actual hash ID of the (one and only) commit A. You will also see this hash ID printed when you run git log.

When we then create a new commit, it gets a new big ugly hash ID, which again we can't predict, but we'll just call it B for short. Commit B will contain, as part of B's information, the actual raw hash ID of commit A. We therefore say that B points to A, and we can draw that too:

A <-B

Having just created B, Git now writes B's hash ID into the name to which HEAD is attached:

A--B   <-- master (HEAD)

That is, master now points to B, and B points to A. We can create a third commit C, and master will now point to C:

A--B--C   <-- master (HEAD)

Let's now create a new branch name dev without switching to it:

git branch dev

The picture now looks like this:

A--B--C   <-- master (HEAD), dev

Now let's switch to dev, using git checkout dev. The current commit remains commit C, and both names master and dev continue to point to commit C, but now HEAD is attachd to dev instead of master:

A--B--C   <-- master, dev (HEAD)

Now let's create a new commit, which gets a new unique big ugly hash ID, but let's just call it D. Git updates the name to which HEAD is attached, too, so let's draw the result:

A--B--C   <-- master
       \
        D   <-- dev (HEAD)

Note that commits A through C are on both branches, but commit D is only on branch dev.

If we now switch back to master (using git checkout master, which selects commit C again) and make another commit E, the picture becomes:

        E   <-- master (HEAD)
       /
A--B--C
       \
        D   <-- dev

The names master and dev each hold just one hash ID, but we can find all the commits by starting at E and D and working backwards. Three of the five commits are on two branches right now. We can, if we like, create a new branch name at any time, pointing to any of these five commits. For instance, if we find the raw hash ID for commit C and run:

git branch feature <hash>

we get:

        E   <-- master (HEAD)
       /
A--B--C   <-- feature
       \
        D   <-- dev

The commits, A-B-C-D on dev, A-B-C on feature, and A-B-C-E on master, are also called branches. It's very important, in Git, to keep in mind that when someone says branch X, they might mean branch name X, which identifies one particular commit. Or they might mean the commit identified by branch name X, plus the commit that comes before it, plus all other earlier commits. Or—because people are human—they might even mean something else. It's up to you to figure out exactly what they really mean.

What someone means is often reasonably clear from context: the phrase the master commits means commit E and zero or more of the earlier ones, rather than the name master itself. But just saying master is ambiguous, and when it matters, it can matter a lot. You might need to ask someone to be more explicit.


3The reasons for this are a bit complicated but one part is quite clear. The new commit has a date-and-time stamp—actually two date-and-time stamps, but one suffices here—and the date and time in it are the moment that you actually create the commit, as shown on your computer's clock. Since we don't know at what exact second you will create the commit in the future, we can't tell you what your new commit's hash ID will be.

Upvotes: 1

Related Questions