User:Damiandudycz/Git-Bisecting

From Gentoo Wiki
Jump to:navigation Jump to:search

Git Bisecting Overview

Git bisecting is an efficient method for identifying the specific commit that introduced a bug or issue into a project. This process uses a binary search approach to narrow down the range of commits, with each commit marked as either "good" or "bad" based on whether it exhibits the issue in question.

  • Good commits are those where the issue is absent.
  • Bad commits are those where the issue is present.


The bisecting process involves the following steps:

  1. The selected part of commit history is divided into two halves, and the commit in the middle is selected for testing.
  2. The user checks if the issue is present in this commit.
    1. If the issue is present, the commit is marked as "bad", and the search continues with the earlier commits.
    2. If the issue is not present, the commit is marked as "good", and the search continues with the later commits.
  3. This process is repeated, with each step halving the range of commits under consideration, until the exact commit introducing the issue is found.


Once the "good" and "bad" commits have been identified, Git will display the specific commit where the problem was introduced.

Preparing for Git Bisecting

Navigate to your project's Git repository directory and ensure there are no local changes by running:

user $git status

If local changes are present, perform the necessary operation to either commit, stash, or remove the changes.

After ensuring there are no local changes, identify the starting "good" and "bad" commits. This step is crucial to reduce the time required to perform the bisecting process by limiting the number of steps needed.

To find the appropriate commits, use the following command to browse the commit history:

user $git log

For lengthy commit histories, consider using the following flags to simplify the output:

Flag Description
--no-pager Displays the entire commit history without invoking a pager, allowing you to view all output without scrolling.
--oneline Condenses the log output to show only the commit hash and summary title for each commit.
user $git --no-pager log --oneline

Review the history to determine the commit IDs for the "good" and "bad" commits. If you are uncertain whether a commit is "good" or "bad," it's better to add more commits in between and perform the bisect process to pinpoint the issue more accurately.

It is important to select a range of commits that contains the introduction of the issue. Otherwise, the bisecting process will not yield accurate results.

Once you've identified the "good" and "bad" commits, start the bisecting process using the following command:

user $git bisect start

This command initializes the bisecting process. You should see the status message:

 status: waiting for both good and bad commits

Finding the Commit that Introduced the Issue

You are now in the process of bisecting, which can be confirmed by running:

user $git status

The process involves marking commits as "good" or "bad" until the exact commit that introduced the issue is identified. Start by marking the initial "good" and "bad" commits, ensuring that the introduction of the issue is somewhere between them.

Mark the "Bad" and "Good" Commit

The "bad" commit is the one where the issue is present. Mark it by running:

user $git bisect bad <commit-id>

Replace `<commit-id>` with the hash of the commit you identified as bad.

The "good" commit is the one where the issue is not present. Mark it by running:

user $git bisect good <commit-id>

Replace `<commit-id>` with the hash of the commit you identified as good.

Git will automatically checkout a commit in the middle of the "good" and "bad" range.

Verify and mark the remaining commits

At this point, you need to verify whether the current commit contains the issue you're investigating. The specific test will depend on the project you're working on. For example, when bisecting the kernel, you might need to build the kernel, run it on your device, and check if the issue is present.

After verifying the presence of the issue, mark the current commit as either "good" (if the issue is not present) or "bad" (if the issue is present):

user $git bisect good

or

user $git bisect bad

After this, Git will proceed with the subset of commits containing the one that introduced the issue, halving the range and checking out the midpoint commit. This process will repeat until Git isolates the exact commit responsible for the problem.

At each step, Git will display a message indicating the remaining steps to complete the process, and next selected commit, similar to this:

Bisecting: 21 revisions left to test after this (roughly 5 steps)
[0fd44ab213bcfb26c47eedaa0985e4b5dbf0a494] mm/readahead: break read-ahead loop if filemap_add_folio return -ENOMEM

The user must verify the results by testing and marking each commit as either good or bad.

Verifying current bisect status

At any point during the bisect process, the user can view the log of the session by using the following command:

user $git bisect log

This command displays a record of the commits and their marked statuses (good, bad, or skipped).

The log is particularly useful for reviewing the history of commit markings, such as when correcting a mistake or understanding the sequence of decisions made during the bisection.

Handling untestable commits

In certain cases, it may be impossible to verify the current commit. This can occur if the code at this commit fails to compile or if testing to determine whether the issue persists is not feasible.

In such situations, the user has the option to skip the current commit. Skipping a commit during a git bisect session excludes that commit and its associated changes from the bisection process. The skipped commit is marked as untestable, and Git proceeds by selecting a new midpoint from the remaining range, excluding any skipped commits.

Warning
If a significant number of commits are skipped, Git may be unable to identify the problematic commit and will notify the user that the bisection cannot continue. Additionally, skipping commits can reduce the accuracy of the process, particularly if the skipped commits are closely related to the issue being investigated.

To skip the current commit, use the following command:

user $git bisect skip

Reviewing Results and Resetting the Bisect Process

Once the final commit has been identified, Git will display the details of the commit deemed to have introduced the issue. This includes the commit ID, author, date, and commit message. These details can be used to review the changes introduced in the commit to determine a potential solution.

It is advisable to save the bisect log at this stage in case the process needs to be repeated or reviewed. To view the entire bisect log, use the following command:

user $git bisect log

Save the output in a location outside the Git repository for future reference.

To examine the changes made by the identified commit, run the following command:

user $git show <commit_id>

Replace <commit_id> with the commit ID provided by Git at the conclusion of the bisect process.

After collecting all the necessary information, you can terminate the bisect process and return the repository to its original state by running:

user $git bisect reset

This will restore the repository to the state it was in before the bisect process began.

Canceling bisect process

The bisect process can be canceled at any time. This may be necessary if the user decides to start over or realizes a mistake was made in marking commits during previous steps.

To cancel the bisect process, use the following command:

user $git bisect reset

This command restores the repository to its original state by switching back to the branch you were on before starting the bisect process and removing any temporary bisection-related state.