Chapter 4

Multiple Commits

A new commit does not have to accept any changes from the workspace. In fact, Git gives the user full control here. In the extreme case, it can be determined what changes should be incorporated in the next commit.

A commit occurs in two steps. First, all changes are collected in a buffer using the add command. This buffer is called the staging area or index. Next, the changes from the staging area are transferred to the repository using the commit command.

Figure 4.1: The route of changes in the repository

The status Command

The status command shows what changes are currently available in the workspace and which of them are already registered in the staging area for the next commit.

> git status 
# On branch staging 
# Changes to be committed: 
#   (use "git reset HEAD <file>..." to unstage) 
# 
# modified: bar.txt 
# 
# Changed but not updated: 
#   (use "git add <file>..." to update what will be committed) 
#  (use "git checkout -- <file>..." to discard changes in ... 
# 
# modified:   foo.txt 
# 
# Untracked files: 
#   (use "git add <file>..." to include in what will be committed) 
# 
# new.txt 
no changes added to commit (use "git add" and/or "git commit -a")

The output shows various headings:

  • Changes to be committed: Lists the files for which changes are to be included in the repository with the next commit.
  • Changed but not updated: Lists the files that have changed, but have not been registered for the next commit.
  • Untracked files: Lists all new files.

It helps that Git indicates what command can be used to change the status again. For example, you can use this command to unstage blah.txt.

git reset HEAD blah.txt

CVS and Subversion users may find the use of the term update here confusing. In those systems, “update” means the acquisition of changes from the repository into the workspace. In Git, however, update is the incorporation of changes from the workspace into the staging area. This is exactly the opposite direction. Babylon sends its regards.

If there are many changes, you can use the --short option to make the output more compact. For instance,

> git status --short 
M  blah.txt 
 M foo.txt 
 M bar.txt 
?? new-file.txt

Selective commits can be very useful to separate changes from one another. Example: A new class has been created. Alongside a few mistakes in other classes have been corrected. Separating the changes into several commits makes the history clearer and makes it easier to selectively deliver single bug fixes earlier (cherry-picking).

However, you should keep in mind that selective commits can create in the repository software versions that have never existed locally. They have therefore never been tested and in the worst case may not even compile. We recommend that you avoid selective commits if possible. It is often sufficient to make a note that you want to fix an error, rather than fix it right away.

The Staging Area Stores Snapshots

One thing you should know about the staging area: it is more than just a list of files for the next commit. It stores not only locations of changes, but also what have changed. For this purpose Git generates a snapshot of the affected files with exactly the selected changes. Figure 4.2 illustrates this. In Line 1, the workspace, the staging area and the repository are still the same. Then, the developer working on the file makes some changes in his workspace (Line 2). He then uses the add command to transfer the changes to the staging area, but not yet to the repository (Line 3)

In Line 4, the developer changes the file again. Now all the three areas have different contents. A commit command transmits the first change to the repository (Line 5). The second change is still in the workspace. The developer then uses the add command to transfer it to the staging area (Line 6).

Figure 4.2: Changes from the workspace are copied to the staging area and to the repository

What To Do with Changes That Are Not To Be Committed?

As it happens, there are things that you do not want to commit, including:

  • experimental changes for debugging purposes
  • changes that are added by accident
  • changes that are not ready yet
  • changes in generated files

Git offers several ways to deal with them:

  • Reset experimental changes or changes made by accident using the reset command
  • Ignore files that you do not want to commit using .gitignore
  • Save changes that you might want to commit later with the stash command

Leaving out Unversioned Files with .gitignore

In general, generated files, temporary files created by editors or backups are files you do not want to put under version control. By adding entries in a .gitignore file in the root directory of the project you can make these files “invisible” to Git. You can specify file paths and directories in it. The wildcard characters “*” and “&” can also be used. You should know the following about paths: A simple path like generated/ will make directories that contain the name, such as src/demo/generated, ignored everywhere, If the path is prefixed with a /, such as in /generated/, then only the exact path—relative to the project’s root directory—will be ignored.

# 
# Simple file path 
# 
somehow/simultaneous.txt 
# 
# Directories ending with a "/" 
# 
generated/
# 
# File types as glob expressions 
# 
*.bak 
# 
# "!" marked exceptions. "demo.bak" 
# will be versioned, but "*.bak"'
# will be excluded.
# 
!demo.bak

You can create a .gitignore file in a subdirectory of your project. In this case, it will affect all files and paths below that directory. This may be useful, for example, if your project is comprised of various programming languages, each of which needs a different configuration.

Note that entries in .gitignore only affect files that are not yet managed by Git. If a file is already versioned, the status command will display all changes to it, and these can also be registered with the add command for the next commit. If you want to ignore files that are already versioned, you can do this with the --assume-unchanged option of the update-index command.

Stashing

If you are in the middle of something and, say, a fix needs to be written quickly, you often want to start making changes but not commit what you have been doing. In this case the stash command can help save changes locally and those changes can be referred to again later.

Summary

  • Staging area: The staging area (also called index) is where you prepare for the next commit. It contains a snapshot of file contents.
  • Adding generated snapshots: You use the add command to create a snapshot of modified files in the staging area. If you change the same files again, the new changes are not automatically included in the next commit.
  • Selective commit: When you use the add command, you can specify which files are to be included in the snapshot. All other files remain unchanged.
  • Selecting sections of code: With --interactive you can even select individual sections of changed rows (hunks). Only these changes are then transmitted as a snapshot in the staging area.
  • Status: The status command shows which files go into the next commit and which files have been modified locally, but are not yet registered in the staging area.
  • Reset the staging area: With git reset HEAD . all files will be reset to the current HEAD version.
  • .gitignore: In this file, you list files and directories that Git should not manage.
  • Stashing: With the stash command you can stash the current changes in the workspace and the staging area. Later, you can retrieve it again with git stash pop.
..................Content has been hidden....................

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