What exactly is git checkout branch — . does?

Question:

I would like to understand this command in an easier way, I did some tests but I am not sure of the conclusion. I have two branches, the master branch and the new branch, and I ran the test described below.

Directory in the last commit of the master brach:

Arquivo    Conteúdo
a.txt      Arquivo a.txt do branch master
b.txt      Arquivo b.txt do branch master

Directory in the last commit of the new branch:

Arquivo    Conteúdo
a.txt      Arquivo a.txt do branch novo
c.txt      Arquivo c.txt do branch novo

Git status:

$ git status
On branch master
nothing to commit, working directory clean

executing the command

$ git checkout novo -- .

The directory was:

Arquivo    Conteúdo
a.txt      Arquivo a.txt do branch novo
b.txt      Arquivo b.txt do branch master
c.txt      Arquivo c.txt do branch novo

Git status:

$ git status
On branch master
Changes to be committed:
  (use "git reset HEAD <file>..." to unstage)
    modified:   a.txt
    new file:   c.txt

It looks to me like it's taking all the files from the new branch, copying and pasting it onto the working directory, overwriting all the files with the same name. That's right, can I count on this behavior? How can git overwrite a file with a different name?

Note that the git checkout command behaves differently depending on the parameters. I'm specifically asking for the version of the command that has some file as a parameter. In the command I mentioned, the point is specifying the current directory (which in this case contains all the files) and it makes a difference in the behavior of the command. Notice the two git statuses that the command doesn't change branches like checkout without "– .".

Answer:

The git checkout branch can be used in the following situations:

1 – Change branch. When git changes branches, any changes that have been applied to the branch will be overwritten by the changes from the checked out branch.

When creating a git repository, the repository already starts with a branch called master. Imagine that at this point you create a master.txt file and commit that file. Next you create a new branch called nova-branch, this new branch, at that time, will have the same content as the master branch. Therefore, when you run the git checkout nova-branch command, no difference will be noticed.

Now imagine that you create a new file called nova-branch.txt and commit that file. At that moment there will be two files: master.txt and nova-branch.txt. When you run the command git checkout master , your working directory will revert to the state the master branch is pointing at, that is, the nova-branch.txt file will disappear, because on the master branch this file doesn't exist.

Now imagine that you create a file called new-file.txt and don't commit that file. The files novo-arquivo.txt and master.txt are present in the current directory. Next you run the git checkout nova-branch command. The working directory will return to the state the nova-branch is pointing to, ie the nova-branch.txt file will appear. However, the new-file.txt file will still appear, this is because this file has not been committed, so it is not part of the master branch. It is in what is called working copy, which are files that have been modified, created or deleted, but not committed. These files will remain in the working copy even if you change branches. That way, if you want, you can commit these files to whatever branch you like.

The examples I gave were over creating files, but of course the same applies if changes are made to the file.

2 – git checkout can be used to create a new branch too. If the command is run like this: git checkout -b nome-branch . The branch will be created and then checked out.

3 – git checkout can be used to locally create a remote branch. If you clone some repository, only the master branch will be created locally. If you want to work on top of another branch, just run the command git checkout nova-branch , and the branch will be created locally.

A nice command you can try is this: git log --all --decorate --oneline --graph .

The git log command will show the history of commits. By putting --decorate you will see which commit each branch is pointing to. --oneline will only show one line for each commit to make it easier to visualize. The --graph will show you at which points the branches forked and at which points they were merged. --all will show the commit of all branches. Without --all only commits from HEAD will be shown, which in this case are commits from the current branch.

In addition to switching branches, git checkout can be used to return a given file to its state in the staged area. The staged area is the files that are ready to be committed. In other words, these are the files that we run the git add command. If there is no version of the file in the staged area, it will be returned to its version from the last commit. Let's imagine the following scenario:

  1. echo algum texto > a.txt
  2. git add a.txt
  3. git commit -m 'adicionando a'
  4. echo alterando texto de a > a.txt

At this point, we don't want to commit the change made to a.txt. We want to undo the change. In that case, we can use the command git checkout a.txt . Changes made to the file will be discarded. This command can also be used in the following ways:

  1. For more than one file: git checkout a.txt b.txt
  2. For a directory: git checkout teste

We can, however, checkout the file to another branch.

In the example you gave what happened was the following: When executing the command git checkout novo -- . All files in the current directory that are in the new branch have been checked out. In that case, files that exist on the master branch and exist on the new branch will be replaced by the version that is on the new branch. Files that only exist in the new branch will be added to the master branch.

The behavior is similar if you are checking out files on the same branch. Let's imagine the following scenario:

  1. The master branch has the following committed files: a.txt and b.txt.
  2. You then remove the b.txt file, change the a.txt and create the c.txt
  3. You then run the git checkout . command git checkout .

See that the behavior will be the same. The a.txt file reverts to the state of the last commit on the new branch, the b.txt file reappears, and the c.txt file keeps appearing, but as untracked.

The difference between these cases are:

  1. git checkout . – Files in the current directory will be returned to their versions in the staged area. If there is no version in the staged area, they will be returned to their versions in the last commit in the branch.
  2. git checkout nome-branch . – The files in the directory will be returned to the last commit version of the desired branch.

In case a new file is created and this file is not committed, when the git checkout . is performed git checkout . , this file will not disappear. This is because git is not aware of this file, as it has not yet been versioned. It will remain in the working copy as an untracked file.

Likewise, if a file only exists on the master branch and does not exist on another branch, when you run the git checkout outra-branch command, that file will not go away, because on the other branch git has no knowledge of that file, so it doesn't will do nothing with it.

For clarification purposes, the "." means that the current directory will be used and not all files. If you are in the root directory then all files will be used. But if you go into some directory and run the command with the ".", all files in that last directory will be checked out.

How can git overwrite a file with a different name?

No. git will only overwrite files with the same name.

If you use the git mv command, git will know that the file has been renamed. If the file is renamed without this command, git will identify that the file with the old name has been removed and that the file has been created with the new name. Still, after running git add for both operations, git will be able to identify that there was a rename. If the file is renamed on a certain branch, when you merge it into another branch that has the old filename, git will know it's the same file and try to merge it. However, the same does not apply if git checkout is used. git won't be able to check out a file on another branch if the file doesn't have the same name. Example:

  1. echo primeira linha > a.txt
  2. git add a.txt
  3. git commit -m 'adicionando arquivo a.txt'
  4. git checkout novo
  5. git merge master
  6. git mv a.txt novoNome.txt
  7. git commit -m 'alterando nome de a para novoNome'
  8. git checkout master

At this point, if you run the command git checkout novo d.txt , git will not find that file in the new branch. If you run the command git checkout novo novoNome.txt , the subsequent file will be brought into the master branch but will not replace the old d.txt.

Scroll to Top