13. Manage Files with Git

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.

Basic Configuration

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.


git status

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


Note

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


Handling a Multiple Location Situation

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.

Telling Git to Ignore a File

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.


Removing Files

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

Handling Branches

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.

Pushing Branches

Recall the command to push changes to the central repository server:

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


Summary

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.135.190.113