"Saving" your files in Git is a bit different than in most programs or editors. In Git nomenclature, 'saving' your code or changes is referred to as committing code. This means that the changes are recorded as 'history' of the current working directory.
A commit is the Git equivalent of a "save". Traditional saving should be thought of as a file system operation. Saving changes ~ https://www.atlassian.com/git/tutorials/saving-changes
A commit applies to the entire directory, and all changes (i.e. removing a file, changing some code, renaming a folder) are 'added' simultaneously in one commit. These commits (saved changes) can be stacked on the developer's local repo before being 'pushed' out to the source repository. This makes it possible for the developer to keep working on a feature (or multiple) without internet connection, all the while keeping a clear working history of his/her changes. When the developer is ready to connect to the source/public repo, all these commits can be pushed in one go and added or merged to the source working history.
A "standard" Git workflow consists of the following: changing files, adding these changes, committing the changes and pushing the changes.
First: Lets create a new Git repository Heads-up : The λ symbol is my terminal's (CMDer) user-prefix symbol. Your's might be '$' or '>' depending on your terminal. The commands are typed after the symbol. When the symbol is omitted on a line, it means that the line is output by the CLI and not typed by me.
1 λ cd ~ git-repo 2 λ git init 3 Initialized empty Git repository in ~/git-repo Now we have an empty git repository to work with. It only has the bare bones files in the .git-folder and it's HEAD (pointer to current branch) points to refs/heads/master.
1 λ cat ~/git-repo/.git/HEAD 2 ref: refs/heads/master Status Using git status is essential in working with Git. It provides a summary of all the changes you have made and the files that are in a different state compared to the recent-most commit. This means that you can see what changes would be stored if you would execute git commit. It is important to regularly run a git status while you are working on your repo, and definitely always run a git status before running a commit! It does not however, show the working directory's commit history, which is shown by git log.
Let's see it in action. First change directory into the newly created git-repo folder and run the git status command.
1 λ cd git-repo 2 λ git status 3 On branch master 4 5 No commits yet 6 7 nothing to commit (create/copy files and use "git add" to track) This lists all the changes Git has seen since your previous commit. As there hasn't been a commit, and the folder is still empty, no commits are listed and the message 'nothing to commit' is displayed. Let's create an empty text file called firist.txt and see what happens!
1 λ touch first.txt Touch is the linux-based command to create a new file, on Windows you can enter the folder and use the right-mouse button to create the file.
Now when we run the ll command (or dir), we should have the .git folder and the first.txt file present in the git-repo folder.
1 λ ll 2 total 8 3 drwxr-xr-x 1 x009461 1049089 0 Apr 16 12:37 . 4 drwxr-xr-x 1 x009461 1049089 0 Apr 16 11:39 .. 5 drwxr-xr-x 1 x009461 1049089 0 Apr 16 11:39 .git 6 -rw-r--r-- 1 x009461 1049089 0 Apr 16 12:37 first.txt Running git status gives us the following:
1
λ git status
2
On branch master
3
4
No commits yet
5
6
Untracked files:
7
(use "git add ..." to include in what will be committed)
8
9
first.txt
10
11 nothing added to commit but untracked files present (use "git add" to track) This tells us we are working on the 'master' branch, we have no commit history for the working directory and that there are untracked files inside the directory: first.txt. Git suggests we run the command git add to start tracking the currently untracked files. What does that exactly mean? This brings us to the point of tracking in Git.
Tracking
After running git init, whether run in an empty folder or existing project folder, all current and future files and folders within a the local repository will be watched by git. Git categorizes files and folders into three types:
Tracked ~ Here a file has been staged (ready for committing) or committed. Untracked ~ File has not been staged or committed Ignored ~ File is explicitly being ignored (specified in the file .gitignore) Currently our first.txt is untracked: the default state for newly created files. Since we only just created the file, and have not specified to Git whether we want to track it for the next commit, Git lists it as such. Let's get this baby tracked so we can commit it to our working directory history.
Add The git add command adds files to the staging area. It basically tells Git that you want the changes to be tracked and included in your next commit so they will persist in the working directory's history. This staging area is the place where all changes are tracked, ready to be committed. It's possbile to do a bunch of changes to your working directory but only add some of the files/changes to the staging area, commit those changes while leaving the other changes out. Later on you could add the other changes to staging and commit those as well (in a single, or separate commits). This way commits can be used with surgical precision, only containing those specific changes the developer wants to add to the commit history.
It's even possible to only add certain parts of a changed file to staging. Maybe you only want to add one function in a specific script to the next commit, even though you changed many parts in the script-file.
Let's try adding our first.txt to staging by using git add [name-of-file].
1 λ git add first.txt 2 λ git status 3 On branch master 4 5 No commits yet 6 7 Changes to be committed: 8 (use "git rm --cached ..." to unstage) 9 10 new file: first.txt We added the first.txt and ran git status, which shows that the file has been added to the changes to be committed: area a.k.a staging. Now if we would run git commit we would create a commit where the single action was the adding of the empty first.txt file to the repo.
Adding all to staging. Above, we specified the name of the file we wanted to add git add first.txt. This is valid and can be done for all the suggested changed when running git status. However, you can run git add . (git add dot) to automatically add all the modified files in the current dir to staging, instead of manually adding them. Another way is to use git add -A or git add --all which does the same, but for the entire repository.
There are a bunch of paramaters/options for add (which you can list by using git add -h), like -n for dry-running (testing without actually moving to staging) and -f for forcing ignored files to be added. Interactive mode is another interesting one, where certain parts/lines of a file can be staged while others are not. It is started by adding -i or --interactive to the git command. Since this is a more advanced topic, we will not divulge in it here. For now, let's finally see what all that committing talk is about!
Committing Since we created a file and added it to the staging area, and are pleased with our work so far, we can commit this to our history. Run the following command to do exactly that: git commit. This should take you to 'editor' mode in the terminal, or perhaps it will open a text editor for you. This is normal procedure, since we are required to add a commit message to the commit. This commit message is the bread-and-butter of our commits, it should specify what the commit is all about and what changes/actions it brings forth. Some adhere to particular messaging styles like using present-tense, imperative-style for a commit message (Add file first.txt) as if giving out orders to your codebase. A lot has been written about best-practices or conventions for commit messages.Git doesn't require commit messages to follow any specific formatting constraints, but the canonical format is to summarize the entire commit on the first line in less than 50 characters, leave a blank line, then a detailed explanation of what’s been changed.
Whatever conventions you use, they should be consistently implemented by you and your team members. Anyway, for now just enter a message, usually the first commit is called "Initial commit" to differentiate it from the subsequent ones. Whatever you choose, the commit message cannot be empty nor can it consists out of a single commented line (starting with #).
1 Initial commit 2
3
4
5
6
7
8
9
10
11
Saving this should result in the following output:
1 [master bae9550] Initial commit 2 1 file changed, 0 insertions(+), 0 deletions(-) 3 create mode 100644 first.txt Here master specifies the branch we are committing to, bae9550 is the hash-code generated to refer to this commit, followed by the commit message Initial commit. 1 file was changed, no insertions or deletions. Finally it displays some 'mode information' containing permissions and the file(s) modified. In this case our first.txt is a (100644): Regular non-executable file.
Commit message in-line. Instead of opening a text-editor to add the commit message, you can add it in-line with the -m [message-here] option. So git commit -m 'This is my message' is a shorter way of creating a commit.
Running git status shows us that there are no untracked files anymore:
1 λ git status 2 On branch master 3 nothing to commit, working tree clean And git log shows us our first and only commit:
1 commit 192f9461f8d1dad6c70fa05658a8443fc20a2f5a 2 Author: labenni [email protected] 3 Date: Mon Apr 16 15:04:11 2018 +0200 4 5 Initial commit We have now succesfully 'saved' a change and created commit! Normally we should push it to a remote repo so it persists beyond our local machine and others could build on our work, although we would have to first configure some remote settings for that. For now, know that you have uncovered much of the regular Git workflow already!