Outline#

This chapter will use a simple example to explore the basic commands you can use on your local repository, including add, commit and push. Before we start, we need to finish some important configurations first so that Git knows who we are. Relax and follow the instructions below.

Configuration#

After finishing the instructions of the last chapter, you may notice that you can directly create or modify files on GitLab. This is because you have already login and thus GitLab knows who you are and what you can do to your own copy. In this chapter, however, we will create and modify files in our local repository. Initially, a local repository doesn’t know who operates on the files. This means we need to specify who we are in the first place before we use any Git commands. Otherwise, Git will use a default username and trigger unnecessary troubles for you.

Note: If you skip this step, you will need more effort to get things right!

  1. First, we need to go into our local repository by using cd [repo-name] command, such as cd comp1720-2023-labs.
  2. Enter git config user.name [Your Name] to set your full name.
  3. Enter git config user.email [uxxxxxxx@anu.edu.au] to set your email address, which must be identical to the one you use to login GitLab.

If you want your full name or email settings to be applied to all local repositories, you can modify the commands in step 2 and 3 to git config --global ... to set the name and email address globally.

That’s all done! You can double check by using git config --list:

$ git config --list
user.name=xxx
user.email=uxxxxxxx@anu.edu.au
...
remote.origin.url=git@gitlab.anu.edu.au:uxxxxxxx/yyy.git
...

If you see your name and email set up, you are ready to head forward.


Add & Commit#

Let’s quickly review Git’s data model:

Git Model

After we make some changes to any file, these changes remain in our working directory. We need to move these changes up to the top layer in two steps. To do this, we first need to use git add command to move changes to the staging area. We then use git commit command to move them from the staging area to the repository layer, where snapshots of all changes are stored in order. Simply follow the instructions below to finish this stage.

Assume we only have a README file after cloning. We can use ls command to double-check. The output may look like this:

$ ls
README.md

We now need to create a new file, contribution.md, in our repository to record each teammate’s contribution. We can use touch command to create this file:

$ touch contribution.md

Now use ls command again to confirm this new file has been created:

$ ls
README.md  contribution.md

If you are using Windows, you will be stuck at the very first step. This is because OS-related commands are different in Windows and Linux. So use File Explorer to create this new file.

Note that Git keeps track of all changes in our repository. So what happens after we create this new file? We can use git status to check out its current status:

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Untracked files:
  (use "git add <file>..." to include in what will be committed)
        contribution.md

nothing added to commit but untracked files present (use "git add" to track)

The output log gives us a lot of helpful information. Don’t panic. Let’s analyse the log together:

  • “On branch main” shows we are at a branch called “main”. Branching is a fundamental feature of Git that allows you to create independent lines of development within a repository. It allows you to work on different things simultaneously, keeping changes isolated. With no additional setting, “main” is the default branch.

You may wonder why we need branching. Imagine an assignment consisting of small tasks, and you agree to work on two of them. In addition, these two tasks are set for two different goals, and they are independent of each other. In this case, you may hope changes made to finish these two tasks can be separated so that any problems belonging to one task wouldn’t interfere with the other. This is what branching is for. By using branching, you can create two independent lines of development and find it handy to focus only on one of them while coding. Branch

  • “Your branch is up to date with ‘origin/main’” indicates that this local branch “main” is up to date with the remote branch “main” on GitLab. You don’t need to update your local branch to stay in sync with the latest changes in the “main” branch on GitLab.
  • “Untracked files” means Git detects new changes to the listed files. In this example, we added contribution.md into our repository. Its snapshot remains in the working directory and needs to be tracked by moving to the staging area.
  • You can see that a snapshot of contribution.md is now at the the bottom layer:
Git Add

The last line suggests how to track new changes: “Use git add to track”. So let’s try it out!

Add#

The syntax of git add command is git add [file_name1] [file_name2] ..., and we need to replace [file_name] with the name/path of that new file:

git add contribution.md

Sometimes you may have made changes to many files. In IDEs like VSCode and Intellij, you can easily select all of them by clicking the “select all” box. How can we do it in command? The easiest way is to replace [file_name] with a single dot ‘.’ , meaning you want to add all changed files: git add . Make sure all files are meant to be added when you are lazy :)

Let’s see what happened by using git status again:

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   contribution.md

Note that the last part of the output log has changed. Now Git recognises that the snapshot of a new file contribution.md is put into the staging area and needs to be committed. Now contribution.md is at the middle layer:

Add

Hang on before we move to the next step! Recall that staging area is like a snapshot before time travel. You may be curious about what does snapshot mean in the given example. Don’t worry. You can quickly comprehend this after reading the section below.

Snapshot#

Read only!!! Note that we have added contribution.md. Assume you and your teammates all agree to distribute your contribution evenly. So you quickly add a new line to this file and save it. What happens in Git now? Does this file stays in the staging area, or is it automatically moved back to our working directory? Let’s find out:

$ git status
On branch main
Your branch is up to date with 'origin/main'.

Changes to be committed:
  (use "git restore --staged <file>..." to unstage)
        new file:   contribution.md

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
        modified:   contribution.md

Looks confusing? How can a file waiting be committed and not staged for commit at the same time? Don’t panic. You have hit the nature of snapshot now.

Assume your repository is an art project consisting of drawings. In Git, a snapshot is like taking a photo of your drawing at a particular moment. It captures how your drawing looks like at that time, and a “commit” may consist of multiple snapshots.

  • The second paragraph starting with “Changes to be committed” shows the first snapshot before we edit contribution.md, which is made when we first created this file.
  • The last paragraph starting with “Changes not staged for commit” indicates that we need to make a new snapshot for Git to keep track of new changes for contribution.md.

They don’t conflict with each other because Git tracks snapshots rather than files themselves. It’s beneficial to remember the concept of snapshot while using Git.

Commit#

To commit new changes, use git commit command: git commit -m "commit message". Simply replace “commit message” with the actual commit message, such as:

$ git commit -m "created contribution.md"
[main 21c83db] created contribution.md
 1 file changed, 1 insertion(+)
 create mode 100644 contribution.md

You may wonder what “-m” stands for and if it’s optional. Actually, this manual uses “-m” for a reason: avoid using the editor Vim/Nano. When you ignore “-m” and only enter git commit, your terminal will change to an editor. Vim/Nano is unlike other editors and can get you stuck if you aren’t familiar. So we can avoid using it by attaching the commit message after “-m” parameter. “-m” stands for “message” and is one of many other parameters that git commit can use. You may find the full documentation if you are interested.

You have successfully made a commit if you see your output log similar to the log above. Double check by using git status again:

$ git status
On branch main
Your branch is ahead of 'origin/main' by 1 commit.
  (use "git push" to publish your local commits)

nothing to commit, working tree clean

Congratulation! Note that the status has been updated. It tells you that “your branch is ahead of ‘origin/main’ by 1 commit” and “use git push to publish your local commits”. Now our local changes in the “main” branch are 1 commit ahead of the remote “main” branch on GitLab. We have successfully moved our changes to the top layer:

Commit

Shortcut?#

You may find it inconvenient to commit changes after following the steps above. But in reality, professional engineers think the opposite. One big advantage of Git is providing you with more fine-grained control by allowing you to stage the changes you need for the current commit and stage the other changes for the next commit.

Imagine you have done lots of work on many files. Compared to compacting everything in a single commit, distributing your changes into different commits facilitates much better traceability for future improvement. You can use this time machine to return to any commit to discover the root of new bugs or rewrite codes for better performance. That’s one reason why engineers like to add changed files manually.

But there’s a shortcut if you don’t want this level of control or only have changed a few files. Use git commit -a -m "commit message" to let Git automatically add and commit all changes with a single command. You don’t need to manually add files before committing if you use the shortcut instead.


After committing, We can finally update the remote branch with the git push command. Hang in there and get ready for the last step!

Push#

Pushing is the act of taking one or multiple changes (commits) made to the repo, each labelled with a commit message, and copying these changes to the remote version on GitLab. After pushing, your teammates can see the updated version of your repository on GitLab with your work added in. They can collaborate with you by progressing their work on top of yours. git push is the command for it:

Push

We now need to push the new file contribution.md to the repo on GitLab. The syntax of push command is git push [remote_name] [branch_name].

But what is [remote_name]? We can check it out with git remote command:

$ git remote
origin

Git answers that “origin” is the name of remote. So we need to push our changes in the “main” branch to our remote repository, which is translated into:

$ git push origin main
Enumerating objects: 3, done.
Counting objects: 100% (3/3), done.
Delta compression using up to 16 threads
Compressing objects: 100% (2/2), done.
Writing objects: 100% (3/3), 305 bytes | 305.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0), pack-reused 0
To gitlab.anu.edu.au:uxxxxxxx/yyy.git
   d3d9858..21c83db  main -> main

You may need to type in your username and password after entering the command, depending on whether you have set up an SSH key.

Remember, you can only push if Git confirms that there are no pending changes to tracked files which have not been committed. This rule is enforced because Git wants to be sure that when a push is made, the states of the local version and the uploaded version are consistent (except for untracked files). In the given example, if you follow the instructions in the previous “snapshot” section but forget to commit, Git will prevent you from pushing because a new change to contribution.md hasn’t been committed.

Congratulation if you see a log output similar to the above one! You just successfully learned how to git push! Now, login to your GitLab account, and you will see your local changes to contribution.md has been updated to your GitLab repo. Well done!

Further Reading#

If you’re interested in learning more about Git commits, pushes, and related topics, here are some resources you can explore:

Moving on#

Now you have learned how to synchronise your local changes to the remote repository. But how to synchronise in reverse? Imagine your teammates see your changes on GitLab and add their changes too. How can you see their changes locally?

In the next chapter, we will learn how to do it using git pull. It might be harder than you expect, but take it easy. Follow the instructions when you are ready, and nothing will stop you!

bars search times arrow-up