Git provides a rich collection of features, but the core set of features are the ones that you are going to use the most often. This includes commands that enable you to stage files and commit files to the local repository, as well as create branches. This chapter focuses on these topics as well as a few related ones.
You might want to perform several configuration operations. For example, you can set your default editor by executing the following command:
ocs@ubuntu:~/ocs$ git config --global core.editor vi
You can view current configuration settings by executing the git config --list
command:
ocs@ubuntu:~/ocs$ git config --list
user.name=Bo Rothwell
[email protected]
core.editor=editor_name
core.repositoryformatversion=0
core.filemode=true
core.bare=false
core.logallrefupdates=true
remote.origin.url=https://gitlab.com/borothwell/ocs.git
remote.origin.fetch=+refs/heads/*:refs/remotes/origin/*
branch.master.remote=origin
branch.master.merge=refs/heads/master
You can store configuration information in multiple locations. One location is in your own home directory:
ocs@ubuntu:~/ocs$ more ~/.gitconfig
[user]
name = Bo Rothwell
email = [email protected]
[core]
editor = vi
An administrator can also store configuration information for all users in the /etc/gitconfig
file. The additional settings that you see when you execute the git config --list
command are either default settings or are derived from the information in the local repository.
Getting Help
Besides looking at man pages for information about git
commands, you might consider the git help
command. When run with no additional arguments, the git help
command provides a synopsis of how the command should be executed followed by a summary of git
commands (config
, add
, clone
, commit
, push
, and so on).
To see information about a specific command, execute git help
command
. For example: git help config
. This automatically puts you in the man page for that command.
In Chapter 12, “Git Essentials,” you learned how to clone an existing repository from a central repository server. You also learned the lifecycle of how local files are committed to the local repository and then pushed to the central repository server:
1. Create the file in the repository directory.
2. Add the file to the staging area with the git add
command.
3. Commit the file to the repository with the git commit
command.
4. Push the file to the central server with the git push
command.
Note
You can combine the git add
and git commit
commands into a single operation by using the -a
option to the git commit
command.
Imagine you are working on some files one day and it’s getting late. It is Friday afternoon and you just can’t wait for the weekend to start. On the following Monday you arrive at work and realize you have no idea in what area you left your file. Were they added to the staging area? All of them or just some? Did you commit any of them to the local repository?
This is when you want to run the git status
command:
ocs@ubuntu:~/ocs$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
It makes a difference which directory you are in when you execute the git status
command. For example, if you are in your home directory, all the files in this directory will be checked to see whether they are in the repository:
ocs@ubuntu:~$ git status
On branch master
Initial commit
Untracked files:
(use "git add <file>..." to include in what will be committed)
.bash_history
.bash_logout
.bashrc
.gitconfig
.lesshst
.profile
.viminfo
ocs/
nothing added to commit but untracked files present (use "git add"
➥to track
)
Make sure you are in the repository directory before running this command!
If you make changes to a file and don’t add it to the staging area, then the output of the git status
command will look like the following:
ocs@ubuntu:~/ocs$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
modified: first.sh
no changes added to commit (use "git add" and/or "git commit -a")
Notice in the previous output the Changes not staged for commit
section. The command output also is helpful in showing you how you can stage the command with the git add
command or stage and commit with the git commit -a
command.
If a file has been added to the staging area, but not committed to the local repository, then the output of the git status
command will look like the following:
ocs@ubuntu:~/ocs$ git add first.sh
ocs@ubuntu:~/ocs$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: first.sh
Changes to be committed
means the modified file is in the staging area but not in the local repository. If a file has been committed to local repository, but not committed to the central repository server, then the output of the git status
command will look like the following:
ocs@ubuntu:~/ocs$ git commit -m "demostrating status"
[master 9eb721e] demostrating status
1 file changed, 2 insertions(+), 1 deletion(-)
ocs@ubuntu:~/ocs$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working directory clean
Note that nothing to commit, working directory clean
means the staging area no longer contains any files and the working directory reflects the current contents of the local repository. Also note the message that states Your branch is ahead of 'origin/master' by 1 commit.
This makes it clear that you need to execute git push
to push the contents of the local repository to the central repository server.
Executing the git status
command after successfully executing the git push
command results in the output demonstrated in the original example of this chapter as shown in Listing 13.1.
Listing 13.1 All files up to date
ocs@ubuntu:~/ocs$ git push -u origin master
Username for 'https://gitlab.com': borothwell
Password for 'https://[email protected]':
Counting objects: 5, done.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 381 bytes | 0 bytes/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To https://gitlab.com/borothwell/ocs.git
3b36054..9eb721e master -> master
Branch master set up to track remote branch master from origin.
ocs@ubuntu:~/ocs$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
nothing to commit, working directory clean
Because of the staging area, the possibility exists to have one version of the file in the local repository, a second version in the staging area, and a third in the working directory. This can happen after you edit a file, add it to the staging area, and then edit the file again. When this happens, the output of the git status
command will look like that shown in Listing 13.2.
Listing 13.2 Three versions of a file
ocs@ubuntu:~/ocs$ git status
On branch master
Your branch is up-to-date with 'origin/master'.
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
modified: first.sh
Changes not staged for commit:
(use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working
➥directory)
modified: first.sh
In the output of Listing 13.2, you can see that the first.sh
file is listed both as Changes to be committed
and Changes not staged for commit
. Now you must make a choice:
Commit both versions of the file—First execute the git commit
command, then execute git add
, and then execute git commit
again.
Commit the last version of the file—First execute git add
and then execute git commit
.1
A useful option to the git status
command is the -s
option, which shows a much more condensed output:
ocs@ubuntu:~/ocs$ git status -s
M first.sh
A showmine.sh
?? hidden.sh
Each file is preceded by up to two characters. The first character indicates the status in the staging area and the second character indicates the status in the working directory. The first.sh
file has been modified in the working directory, but you can tell that it has not been staged yet because of the space character in front of the "M" character. Note the difference if the file is staged:
ocs@ubuntu:~/ocs$ git add first.sh
ocs@ubuntu:~/ocs$ git status -s
M first.sh
A showmine.sh
?? hidden.sh
The A
for the showmine.sh
file means this is a new file that has been staged (because the A
is in the first column), but it hasn’t been committed to the repository yet. The ??
means that hidden.sh
is new and hasn’t been staged or committed yet. Any file that is up to date in the local repository is not listed when you execute the git status -s
command.
In some cases, you want to have a file in the working directory but not have it ever staged or placed in the repository. For example, maybe you want to keep track of some notes about the project, but only for your own purposes. Of course, you could just never add this file to the staging area, but this would mean that git status
will never return nothing to commit, working directory clean
.
To have git
commands ignore a file, create a file named .gitignore
in the working directory and place the filename to ignore inside of this file:
ocs@ubuntu:~/ocs$ touch notes
ocs@ubuntu:~/ocs$ git status -s
?? notes
ocs@ubuntu:~/ocs$ vi .gitignore #added notes as shown below:
ocs@ubuntu:~/ocs$ cat .gitignore
notes
ocs@ubuntu:~/ocs$ git status -s
?? .gitignore
Notice that you must also place the .gitignore
file itself in the .gitignore
file:
ocs@ubuntu:~/ocs$ git status -s
?? .gitignore
ocs@ubuntu:~/ocs$ vi .gitignore #added .gitignore as shown below:
ocs@ubuntu:~/ocs$ cat .gitignore
notes
.gitignore
ocs@ubuntu:~/ocs$ git status -s
Note
You can also use wildcard characters (*, ?, and [range]) in the .gitignore
file to match a collection of files. For example, I like to name my own files with a .me
extension. In the .gitignore
file I include the pattern *.me
to have the git
commands ignore all of my files.
You can use a pattern that ends with a /
to indicate an entire directory.
If You Are Following Along…
I’ve tried to make this process as transparent as possible, but there are some cases in which I am going to be executing some commands that don’t show up in the body of the text. For example, at this point I have added several versions of the first.sh
file (as well as two new files: the showmine.sh
and hidden.sh
files) to the local repository. I want to use these in later examples, so I decided to push them to the central repository server:
ocs@ubuntu:~/ocs$ git push -u origin master
Username for 'https://gitlab.com': borothwell
Password for 'https://[email protected]':
Counting objects: 10, done.
Compressing objects: 100% (7/7), done.
Writing objects: 100% (8/8), 865 bytes | 0 bytes/s, done.
Total 8 (delta 1), reused 0 (delta 0)
To https://gitlab.com/borothwell/ocs.git
9eb721e..07bb91c master -> master
Branch master set up to track remote branch master from origin.
However, this isn't critical to the topic at hand, so I opted not to show this in the main text. In the future, if I do some "behind the scenes" commands, I will mention the commands that I executed in a footnote. That way if you are following along, you should end up with the same results that I do.
Suppose one day you create a file purely for testing purposes and then, without really thinking about it, you commit it to the local repository:2
ocs@ubuntu:~/ocs$ git add test.sh
ocs@ubuntu:~/ocs$ git commit "update 27"
Later, you realize your mistake and want to remove the file. Simply removing it from the working directory isn’t enough, as demonstrated in Listing 13.3.3
Listing 13.3 Deleting file from working directory
ocs@ubuntu:~/ocs$ rm test.sh
ocs@ubuntu:~/ocs$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Changes not staged for commit:
(use "git add/rm <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory)
deleted: test.sh
no changes added to commit (use "git add" and/or "git commit -a")
Notice the suggestion to execute the git rm
command, which will stage the file for removal from the repository. See Listing 13.4 for an example of the git rm
command.
Listing 13.4 Staging a file to be deleted
ocs@ubuntu:~/ocs$ git rm test.sh
rm 'test.sh'
ocs@ubuntu:~/ocs$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
Changes to be committed:
(use "git reset HEAD <file>..." to unstage)
deleted: test.sh
Lastly, perform a git commit
command to remove the file from the repository:
ocs@ubuntu:~/ocs$ git commit -m "deleting test.sh file"
[master 2b44792] deleting test.sh file
1 file changed, 1 deletions(-)
delete mode 100644 test.sh
You decide that you want to test some new features of the project that you are working on, but you don’t want this to impact the current development process. This is an ideal time to create a branch.
When you first create a project, the code is associated with a branch called master
. If you want to create a new branch, execute the git
branch
command:
ocs@ubuntu:~/ocs$ git branch test
This doesn’t mean you are suddenly working in the new branch. As you can see from the output of the git status
command, the git branch
command doesn’t change your current branch:
ocs@ubuntu:~/ocs$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working directory clean
The first line of the output of the previous command, On branch master
denotes that you are still working in the master
branch. To switch to the new branch, execute the git checkout
command:4
ocs@ubuntu:~/ocs$ git checkout test
Switched to branch 'test'
Switching actually does two things:
Makes it so any future commits occur on the test
branch
Makes it so the working directory reflects the test
branch
The second item makes more sense with a demonstration. First, observe the following commands, which will end up with a new version of the hidden.sh
file being placed in the test
branch repository:
ocs@ubuntu:~/ocs$ git add hidden.sh
ocs@ubuntu:~/ocs$ git commit -m "changed hidden.sh"
[test ef2d7d5] changed hidden.sh
1 file changed, 1 insertion(+)
Note what the file looks like in the current working directory:
ocs@ubuntu:~/ocs$ more hidden.sh
#!/bin/bash
#hidden.sh
echo "Listing only hidden files:"
ls -ld .* $1
If we switch the project back to the master
branch, you can see how the hidden.sh
file in the working directory is different (note the missing echo
line, which was added for the test
branch only):
ocs@ubuntu:~/ocs$ git checkout master
Switched to branch 'master'
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
ocs@ubuntu:~/ocs$ more hidden.sh
#!/bin/bash
#hidden.sh
ls -ld .* $1
You can see the changes that are made on different branches, along with the comments you provided for each change, by using the git log
command:
ocs@ubuntu:~/ocs$ git log --oneline --decorate --all
ef2d7d5 (test) changed hidden.sh
2b44792 (HEAD, master) deleting test.sh file
19198d7 update 27
07bb91c (origin/master, origin/HEAD) adding showmine.sh and hidden.sh
75d717b added first.sh
9eb721e demostrating status5
3b36054 added first.sh
12424f5 add README
The--
online
option has the git log
command provide a one-line summary of each change. The--
decorate
option requests additional information such as the branch name. The--
all
option asks to see the log for all branches, not just the current branch.
git push -u origin master
Did you wonder at the time what the word master meant? You can probably guess now that it was the branch that you were pushing to the central repository. If you wanted to push the test
branch, then you would have to execute the following command as well:6
git push -u origin test
There is more to the story of branching besides just creating a branch and switching back and forth between branches. For example, at some point you might want to merge files from branches together. You might also want to see how versions of files are different between different branches. Chapter 14, “Manage Differences in Files” covers these topics.
Git Humor
“Be careful not to remove the branch you're standing on.”
—Anonymous
After reading this chapter, you should have a firm understanding of how the working directory, staging area, and local repository work. You should also know how to determine which of these locations a file is currently "in" as well as how to specify files that the git
commands should ignore. You should understand the basics of branching, including how to create branches, switch between branches, add/commit in different branches, and push different branches to the central repository server.
1 The resulting output of this git commit
command tends to cause confusion: 1 file changed, 2 insertions(+), 1 deletion(-)
. Because two versions of the file were staged (two insertions), one had to be deleted before the other was committed to the repository.
2 This potential mistake might be the reason why you must execute git add
and then git commit
for new files (you can't just execute git commit -a
to add a new file).
3 However, nothing is wrong with executing a regular rm
command because you probably want to delete this file from the working directory. This just isn't going to end up removing it from the repository.
4 You can create a branch and switch to it by using the -b
option to the git checkout
command: git checkout -b test
5 Just a side note for those of you paying close attention: the spelling error (demostrating, when it should be demonstrating) is actually how the output of the command was displayed.
6 If are following along, you should know that I did execute both git push
commands to update the master
and test
branch. I use this data in Chapter 14 examples.
3.144.151.126