1

Before my questions, I would like to know if my understanding of some Git concepts is correct, and please feel free to correct me:

  • a branch name points to the tip (i.e. the end commit) of a branch, and
  • HEAD points to the branch name of the current branch, and
  • the current branch is defined as the branch checked out into the working directory.

Here are my questions:

  1. When a new commit is added to a branch by a git command (any git command that can add commits to a branch),

    Questions:

    does the git command always move the branch name forward to point to the new commit?

    Or are there git commands, which add new commits to a branch, which do not move the branch name and thus require me running some additional git command to move it?

  2. When

    • a new commit is added to the current branch by a git command and
    • the branch name is moved forward to point to the new tip commit in the current branch,

    Questions:

    • is it necessary to update HEAD additionally?

      My guess is no, because HEAD has already pointed to the current branch's name, the current branch's name has already been updated to point to the new tip commit of the current branch, and moving the current branch's name doesn't change the fact that HEAD points to the current branch's name. So all looks fine without additional change to HEAD.

    • has the working directory already been updated to be the same as the new tip commit of the branch?

      Or can the working directory still be the same as the previous tip commit of the branch, and, in order to check out the new tip commit of the current branch into the working directory, I need to run some additional git command?

    The followings are two cases/examples with concrete git commands (git push and git pull), which made me think of and ask the above two parts' questions for arbitrary git commands that can add commits to a branch or to the current branch:

  3. git push adds new commit(s) to a branch on the remote repository.

    Now suppose

    • the remote repository isn't bare i.e. has a working directory, and
    • right before pushing, the current branch of the remote repository is the branch to push to.

    Questions:

    • in the remote repository, does git push move the branch name to point to the new tip commit?

      Or does the user of the remote repository have to run some additional git command to move it?

    • In the remote repository, does git push update the working directory to be the same as the new tip commit?

    • I.e. in the remote repository, is the updated version (by git push) of the current branch ("current" before git push) still the current branch after git push? (note the definition of a current branch I gave at the beginning of the post: "the current branch is defined as the branch checked out into the working directory.")

    My guess is no, if I understand correctly from Version Control with Git by Loeliger 2ed which says:

    Recall that the git push command does not check out files in the receiving repository. It simply transfers objects from the source repository to the receiving repository and then updates the corresponding refs on the receiving end.

    In a bare repository, this behavior is all that can be expected, because there is no working directory that might be updated by checked out files. That’s good. However, in a development repository that is the recipient of a push operation, it can later cause confusion to anyone using the development repository.

    The push operation can update the repository state, including the HEAD commit. That is, even though the developer at the remote end has done nothing, the branch refs and HEAD might change, becoming out of sync with the checked out files and index.

    A developer who is actively working in a repository into which an asynchronous push happens will not see the push. But a subsequent commit by that developer will occur on an unexpected HEAD, creating an odd history. A forced push will lose pushed commits from the other developer. The developer at that repository also may find herself unable to reconcile her history with either an upstream repository or a downstream clone because they are no longer simple fast-forwards as they should be. And she won’t know why: the repository has silently changed out from underneath her. Cats and dogs will live together. It’ll be bad.

  4. In git pull command, the merge step merges the newly fetched remote tracking branch into the current branch. If I am correct, the merge step of git pull also advances the banch name of the branch to point to the new top commit on the branch.

    Question:

    • In the local repository, does git pull update the working directory to be the same as the new fetched tip commit?

    • I.e. In the local repository, is the updated version (by git pull) of the current branch ("current" before git pull) still the current branch after git pull? (note the definition of a current branch I gave at the beginning of the post: "the current branch is defined as the branch checked out into the working directory.")

    I have asked the question about git pull at Does git pull check out the current branch after its merge/rebase step?. From my understanding, what Joseph's reply means is git pull checks out the new fetched tip commit into the working directory of the local repository, and I don't need to run additional git commands to check it out. torek's reply is great, but it will be a while until I could understand it.

Community
  • 1
  • 1
Tim
  • 1
  • 141
  • 372
  • 590
  • 3
    I don't suppose you'd consider separating those questions out into separate questions? – Paul Hicks Dec 30 '15 at 18:13
  • I understand the length might be a turn off. But I was writing to my best. I think putting them together will make my questions and the intention behind the questions much clearer, at least to me. The questions are not loosely related, but have the same intention which the title suggests. I appreciate anyone who can answer some if not all the questions. – Tim Dec 30 '15 at 18:17
  • In part 1, `Or are there git commands, which add new commits to a branch, which do not move the branch name and thus require me running some additional git command to move it?` I think the answer has to be no, since we have no definition of what it means for a commit to be "in a branch" other than "it is an ancestor of the current branch tip". The only way a new commit, with no descendants, can be added to a branch is by making it the branch tip. See also: [Finding what branch a git commit came from](http://stackoverflow.com/q/2706797/2404501) –  Dec 30 '15 at 18:31
  • 3
    No offense, but you could spend half of the time you spent on writing this question to actually try 90% of you examples and learn it by yourself. Also part of your examples are really far from the real-life git usage. It might be much more useful for you to work with git in the project and ask questions about concrete problems you faced instead of this theoretic questions. – Yaroslav Admin Dec 30 '15 at 18:36

2 Answers2

3

1. Does the git command always move the branch name forward to point to the new commit?

Yes whenever you do a commit in a branch it moves it to the latest commit.

2. Is it necessary to update HEAD additionally?

No as HEAD refers to the commit at the tip of the current branch, and if you are committing new changes to this checked-out branch, then again the HEAD points to the latest commit.

3. Has the working directory already been updated to be the same as the new tip commit of the branch?

Yes the working directory gets updated the moment you do a new commit, and if after committing a new change in branch A you checkout to an older branch B, then the working directory points to the older branch B with its own latest commit.

4. In the remote repository, does git push move the branch name to point to the new tip commit?

Yes if we do git push from our local repository branch A to remote repository which also has a working directory pointing to branch A, it moves it to the latest commit. There is no need for the user to run any additional commands.

If you push code from branch B(local repository) to branch B (remote repository) which has the working repository as branch A, it does move branch B to the latest commit but the working directory still points to branch A in remote repository. It only updates the code of the branch to which you push the new commits, there is no checkout happening.

5. In the local repository, does git pull check out the new fetched tip commit into the working directory?

No git pull does not check out the new fetched tip commit, it merges the remote branch commits to the current branch in the working directory. You can be pulling code from branch B to branch A, which merges branch B commits to branch A commits, but it doesn't change the current branch to B.

6. Is the updated version (by git pull) of the current branch ("current" before git pull) still the current branch after git pull?

Yes the current branch remains the same even after git pull as explained above, as it just merges the commits.

Sahil
  • 3,338
  • 1
  • 21
  • 43
  • Thanks. My question "5. In the local repository, does git pull check out the new fetched tip commit into the working directory?" Like you said, `git pull` doesn't do check out but merge or rebase. My question should be "5. In the local repository, does git pull update the working directory to be the same as the new fetched tip commit?" What is your answer to it then? – Tim Dec 30 '15 at 20:12
  • Yes it does update the working directory (which is actually the current branch) to be the same as the new fetched tip commit. – Sahil Dec 30 '15 at 22:37
2

There are a few issues with your understanding of Git which I’ll try to clear up:

First of all, commits are not added to branches. Commits are created within the repository, usually pointing to a parent, and then branches may be updated to point to that new commit.

does the git command always move the branch name forward to point to the new commit?

There are ways to create commits without affecting any branch; and if you are on a detached HEAD, you also don’t have any branch updated after commit.

Unless you are on a detached HEAD (which Git will warn you about once you enter it), you shouldn’t worry too much about having to update a branch later on manually. The usual commands you use to create (or recreate) commits are git commit, git merge and git rebase (in addition to fetching existing commits from elsewhere of course), and they all affect the current branch.

is it necessary to update HEAD additionally?

Again, unless you are on a detached HEAD, HEAD will always be a relative reference to another branch or reference. So once that updates, HEAD will implicitly update as well. And if you are on a detached HEAD, then Git will update HEAD directly when you create commits.

has the working directory already been updated to be the same as the new tip commit of the branch?

The working directory is completely separate from commits or branches. Yes, when you do git checkout to switch a branch, or some other commit that directly affects the working directory, then the working directory will update, but committing in particular will not modify the working directory at all. Usually, you add changes from the working directory to the index, and then you create the commit from the index. So the working directory stays in whatever state you left it before committing. Theoretically, the working directory can be something completely different from what you just committed.

git push adds new commit(s) to a branch on the remote repository.

No, git push will communicate with the remote directory and then transfer existing commits to it.

in the remote repository, does git push move the branch name to point to the new tip commit?

When you push to a checked out branch of a remote repository, you usually get a warning and Git will not allow you to do so. But Git will never update the working directory of the remote repository; it cannot do that. You could only do that via hooks that run on the remote repository itself.

A better practice is to push to a bare repository, and that then has a hook that updates another repository with a working directory (on the same machine).

If I am correct, the merge step of git pull also advances the banch name of the branch to point to the new top commit on the branch.

Merging updates the branch, yes.

In the local repository, does git pull check out the new fetched tip commit into the working directory?

Git will try to do that but if it finds conflicts because of uncommited changes, it will not do that and abort before checking out anything.

poke
  • 369,085
  • 72
  • 557
  • 602