“This is the 12th day of my participation in the Gwen Challenge in November. Check out the details: The Last Gwen Challenge in 2021.”


Where is submitted

Almost all Git commands need to know what is currently being committed. For example, git commit needs to know where the current commit is, because it will be the parent of the new commit immediately.

For example, in one of my warehouses, we are in af64eba commit. How does Git know?

You probably know that HEAD can be used to refer to the current commit.

For example, git show HEAD shows the commit information for the current commit and the changes it introduces. All git state is stored in the.git directory, which includes the file that tells us where we are:.git/HEAD.

Write some code and let’s look at what it says. Note: These examples use synchronous I/O to keep an eye on git internals. There are many opportunities to perform file system operations in parallel, so using asynchronous I/O can significantly improve performance.)

use std::fs;
use std::io;

const HEAD_FILE: &str = ".git/HEAD";

fn get_head() -> io::Result<String> {
  fs::read_to_string(HEAD_FILE)
}

fn main() -> io::Result< > () {lethead = get_head()? ;println!("Head file: {:? }", head);
  Ok(())}Copy the code

Running this code yields the following results:

Head file: "ref: refs/heads/main\n"
Copy the code

The.git/HEAD file tells us that we have cut out the main branch.

That’s part of what we want to know, but we still don’t know how Git knows what commit main refers to.

It turns out that refs/heads/main is actually the name of a file in the.git directory. Read it:

use std::path::Path;

const BRANCH_REFS_DIRECTORY: &str = ".git/refs/heads";

fn get_branch_head(branch: &str) -> io::Result<String> {
  let ref_file = Path::new(BRANCH_REFS_DIRECTORY).join(branch);
  fs::read_to_string(ref_file)
}

fn main() -> io::Result< > () {let main_head = get_branch_head("main")? ;println!("main: {:? }", main_head);
  Ok(())}Copy the code

The results show:

main: "af64eba00e3cfccc058403c4a110bb49b938af2f\n"
Copy the code

If you recall, the commit we created was called: af64eba, and it’s no coincidence that.git/refs/heads/main starts with these hexadecimal numbers.

This complete string of 40 hexadecimal digits (representing 20 bytes) is called a “commit hash.”

We’ll see how it evaluates soon (and why it’s called “hash”), but for now you can think of it as a unique identifier for the submitted file.

It is also possible (though less common) for the check out operation to cut out a specific commit rather than a branch. For example, we can run Git Checkout AF64eba to cut out the current commit.

Note: switching to 'af64eba'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by switching back to a branch.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -c with the switch command. Example:

  git switch -c <new-branch-name>

Or undo this operation with:

  git switch -

Turn off this advice by setting config variable advice.detachedHead to false

HEAD is now at af64eba Initial commit
Copy the code

In this case, the.git/HEAD file directly specifies the commit hash:

Head file: "af64eba00e3cfccc058403c4a110bb49b938af2f\n"
Copy the code