Manage and share files with Git


Rebasing is another Git approach for applying changes from one branch to another. In contrast to the merge, a rebase is about moving the starting point of a branch (at least in the scope of this article). The corresponding command is

git rebase mybranch

Figure 4 shows the basic procedure. The gray mybranch block shows the status before the rebase, the blue mybranch' reflects the status after the rebase. The

git checkout mybranch
git rebase master

commands move the starting point of mybranch from MB to MD. Both commands can be combined to:

git rebase master mybranch
Figure 4: Rebasing moves the starting point of a branch.

Thanks to the rebase, versions ZA and ZB receive the changes from MB and MC. The new versions ZA' and ZB' are created. An occasional rebase prevents the branches from drifting too far apart.

The resulting structure corresponds to that shown in Figure 2. Since the head of mybranch is based on the last commit of master, you can perform any required function testing on mybranch and then use a fast-forward merge to merge the branches in the direction of the master, which avoids having an untested master version – unless you changed something there in the meantime.

Note that manual comparisons of branches before merging or rebasing help identify potential problems. You can use either of the commands

git diff <Branch1> <Branch2>
git difftool <Hash1> <Hash2>

to perform a diff.

If conflicts occur, Git displays the corresponding files and interrupts the process. After you have resolved the conflicts,

git add -u

adds the adaptations to the index, and a subsequent

git rebase --continue

resumes the process.

The manual changes become part of the branch you are moving. The master branch remains unchanged in this case. The

git rebase --abort

command aborts the process and restores the previous state.

Rebasing changes the branch starting point, but in the history, it looks as if development in a branch took place linearly. Do not apply this technique to commits that you have already uploaded to a public repository.

From a functional point of view, a rebase cancels existing commits and creates new ones instead. For anyone who has downloaded this branch before your rebase and used it as a basis for their work, it inevitably leads to an additional, and unnecessary, merge. In turn, others uploading their changes to the public repository leads to a merge, because the new branch appears to have changed. You actually have already made these changes with the rebase.

Such actions make the path of the project confusing and complicated. The section "The Perils of Rebasing" in the Pro Git book [3] describes these problems in detail with an example.

Full Speed Astern

What if you want to correct a spelling error in a version that was finished months ago? Suppose you want to change a version (e.g., hash 4fb2717) of the project in Figure 1. The changes and extensions added in the following versions might not be part of the resulting version. No problem: You can use the hash and any tags assigned to it to identify and check out the version uniquely (Listing 4).

Listing 4

Checkout by Hash

$ git checkout 4fb2717
Note: checking out '4fb2717'.

The version is now in what is known as a detached head state. You can look around, make experimental changes, and commit them again. You can also discard all commits you make in this state without affecting any branch by performing another checkout.

If you want to create a new branch for your commits, do so (now or later) by checking out again with the -b option. In the example from Listing 5, the last line says that the working directory has the same status as version 4fb2717.

Listing 5

New Branch

$ git checkout -b mybranch
HEAD is now at 4fb2717... added hello.txt

What does this text mean, and what does the detached head mean? At the end of the day, all of this shows that the checked-out version is already archived and therefore immutable. Preventing changes to checked-in versions is one of the main tasks of a version control system. Git recommends creating a new branch and working on it. Handling a detached branch is not recommended (see box "Completely Detached").

Completely Detached

The state of a detached head, a "detached state" in Git-speak, means that the HEAD pointer does not point to a real branch. Instead, it points to a previously saved, and thus immutable, version. Git itself does not mind; it allows all actions even in this state.

Figure 5 shows a project with a detached branch (based on 4fb2717) on which a commit has occurred (cec704b). As long as you are in this area, the commit remains visible. If you switch to another branch, you can only reach the commit by specifying the hash. It is also difficult to transfer such a commit to the remote repository.

Figure 5: No bindings – a detached branch points to a previously saved version.

If you've checked in changes to the detached head despite the warnings, you can use

git branch <name> <hash>

to convert it to a normal branch. This only works, however, as long as you do not change the branch. You can get the hash with git log.

If you no longer need a branch, you can delete it with

git branch -d <branch>

… if you merged it with another branch, that is. If you want to delete without merging, use -D – note the uppercase D.

Git offers very simple branch handling, and it is quite common to create several branches a day. Some available Git server extensions, such as Gitolite, also allow you to control access to individual branches.

Modifying Directories

Before every change to a directory structure, back up the current status. The subcommands rm (remove) and mv (move) make such changes. Both work on files or folders.

For more extensive changes, it might be useful to make the changes first and then check them in: Test the new structure of the directories, update the Git index, get an overview with git status, and then check in the new status. Figure 6 shows the output of git status after some project files have been moved to subdirectories.

Figure 6: Once the changes to the directories are complete, it is best to have a quick look at the status of the working directory.

The changes are applied with the commands from Listing 6. The first command updates the Git index. In the example shown in Figure 6, three files in the working directory were deleted, so Git removes them from the index. The command in the second line includes the newly created directories, including the files they contain in the index. The last command finally registers the project.

Listing 6

Applying Changes

$ git add -u
$ git add part1 part2 archive
$ git commit -m "Structure changed"

If you get lost during the conversion, you should update the working directory and then delete from the working directory the files and directories that are not in the Git index:

git reset --hard
git clean -df

Buy this article as PDF

Express-Checkout as PDF
Price $2.95
(incl. VAT)

Buy Linux Magazine

Get it on Google Play

US / Canada

Get it on Google Play

UK / Australia

Related content

  • Branch Management

    Git makes version control as simple as possible. To manage your Git branches successfully, you need to learn the ins and outs of git branch and git merge.

  • Tree View

    Complex Git projects sometimes require a better view of the dependencies and branches. Several tools offer GUI options for Git. We take a look at gitk, gitg, git-gui, and GitAhead.

  • Git Ready

    If you develop open source software, you need to know how to use Git. Information on Git fills books, but this basic overview will get you started with a vital open source development tool.

  • Git 101

    When several people collaborate on source code or documents, things can get messy fast. Git provides a quick cure: The distributed versioning system reliably ensures the integrity and consistency of data with minimal effort.

  • Perl: Collaborate with GitHub

    GitHub makes it easier for programmers to contribute to open source projects by simplifying and accelerating communications between project maintainers and people willing to contribute.

comments powered by Disqus
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters

Support Our Work

Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.

Learn More