Git and its workflows can be initially hard concepts to wrap our heads around.
Git is a version control system that lets us keep track of and manage code history. Github is a cloud-based hosting service that helps to manage Git repositories (repos).
Some cool things about Git are that it's based off of a branching model and it's mostly local. Github, on the other hand, is exclusively remote/cloud-based, which allows different people to view, clone, and collaborate with our code.
Flow of Data with Git and Github
Our workflows are going to follow the interaction between our machine (local changes via Git) and the hosting service (remote changes stored via Github history).
For the purposes of simplicity, from this point onwards we're going to use 'local' and 'remote' keywords to refer to our local machines and remote repositories/branches.
Data can be considered within two types:
(a) dynamic instance data, such as code files and their contents
(b) static metadata, such as our branches and commits with user information (or 'git blame' data)
At a high level we could say that our data moves from local locations to remote locations and vise versa
Walkthrough of personal workflow
Now what happens when we make changes locally and how do we do that?
After we copy the remote's repository with git clone
, we are able to work within Git's branching system locally.
When we git pull
we're pulling a copy of a specific branch from the remote repository to our local workspace. If there haven't been any changes to the remote repository, then when we git pull
we will get an 'Already up to date' message.
user@ repo-name % git pull origin main
From github.com:adelinealmanzar/repo-name
* branch main -> FETCH_HEAD
Already up to date.
We should git pull
only the remote branch name that matches the local branch we are currently in.
We can check which branch we're currently located in with git branch
.
user@ repo-name % git branch
* master
Imagine your master or main branch is the trunk of a tree. Whatever branches we create out of that trunk will be almost like draft branches because they will only exist in our local workspace and then eventually into our local repository, where those draft branches will be reviewed and edited.
When we git checkout -b any-new-branch-name
we're creating new local branches off of the master/main root branch and we're moving to that branch.
user@ repo-name % git checkout -b any-new-branch
Switched to a new branch 'any-new-branch'
We can do git branch
again to sanity-check that we're in fact in our new branch
user@ repo-name % git branch
* any-new-branch
master
Our new branch will end up tracking the version history of our changes via commits. But before we commit to our official remote repository history, we must stage those changes in our index. We can check which files are staged via git status
. git status
displays files that have (or have not) been changed in the working directory and the staged directory.
If we've made no changes to any files, running git status will tell us that we have a clean working tree
user@ repo-name % git status
On branch any-new-branch
nothing to commit, working tree clean
So lets add some code changes and then see what git status looks like.
user@ repo-name % git status
On branch any-new-branch
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: src/components/Header.js
modified: src/components/MainContainer.j
no changes added to commit (use "git add" and/or "git commit -a")
Any modification that we make to a file will show up under our workspace area(located after 'changes not staged for commit' in red). In order to add those changes to our index, we must run git add <file-name>
.
user@ repo-name % git status
On branch any-new-branch
Changes to be committed:
(use "git restore --staged <file>..." to unstage)
modified: src/components/Header.js
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: src/components/MainContainer.js
git add
adds new or modified files (from our workspace) to our staging area (located after 'changes to be committed' in green). git add
gives us the benefit of choice in deciding which files and changes we would like to commit. Based on Github's Git Guides, commits should be logical, atomic units of change. Tech teams usually organize their commits based on whichever rule of logic their organization/company practices. An example rule may be that each commit must contain all changes made to an individual file or that each commit must bucket one specific value within a feature. Why implement logical rules for commits? A clean commit history is usually easy to read, helpful for debugging, and helpful for understanding which changes we might end up needing to revert.
To add our changes to an individual commit and create an easy-to-understand commit message, we run git commit -m "any commit message"
user@ repo-name % git commit -m "perf: cleanup/removed debugging comments"
[any-new-branch 71a72da] perf: cleanup/removed debugging comments
1 file changed, 1 insertion(+), 1 deletion(-)
Commit messages should describe what kind of change we've made to our code. In the above example, our commit message indicates that our changes included file cleanup of removing some sudo-code that was no longer needed. The perf
header indicates that the change we made was a removal. This perf
header is one of several semantic-release headers and footers that we can add to our commit message to indicate the type of change we've made to our code (addition, removal, patch/fix, or breaking change). To read more on semantic headers, you can read more here.
After we've committed our changes, we can git log
to view our commit history and sanity check that our commit is in the right place in history. The log commits are in order of most to least recent, so our most recent commit should be at the top, which we can see in the code below.
commit 71a72da43ca6cdd9774c8abf00a96fb3f6c6d0b9 (HEAD -> any-new-branch)
Author: Adeline Almanzar <almanzar.adeline@gmail.com>
Date: Sun Feb 13 11:31:50 2022 -0800
perf: cleanup/removed debugging comments
commit 84c056344662503041c6fd3d5365f805dfca08e8 (master)
Author: Adeline Almanzar <almanzar.adeline@gmail.com>
Date: Mon Feb 7 20:38:54 2022 -0800
third deliverable
Each commit in the log will have a commit ID, information on the author of the commit, the date & time of the commit, and the commit message.
Now that we've committed our changes and done our sanity-checking, at this point we can keep going through the changes workflow to continue committing our changes to our local repository.
Once our local repository is at a ready-enough state for our team's review and/or collaboration, we can push our changes to the remote repository with git push origin <branch-name>
.
user@ repo-name % git push origin any-new-branch
Enumerating objects: 29, done.
Counting objects: 100% (29/29), done.
Delta compression using up to 8 threads
Compressing objects: 100% (28/28), done.
Writing objects: 100% (28/28), 286.05 KiB | 3.11 MiB/s, done.
Total 28 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:adelinealmanzar/repo-name.git
84c0563..71a72da any-new-branch -> any-new-branch
git push
will send all of our local repository's commits and branches to the remote repository (in Github). When we sign into Github and visit the remote repository, we should be able to create a new pull request(PR). We can think of our pull request as a form that we submit to our team with the request to officially merge our changes to the remote branch we originally branched-off of. PRs enable us to share the purpose of our code changes in layman's terms. They also enable our team members access to review our changes and make changes themselves (stay tuned for my next blog post on collaborative workflows).
TLDR: Personal Workflow Summary
-
git clone repo-link && cd repo-name
: make a clone/local copy of the remote repository and move into it -
git branch
: view current branch & view all branches in our local repository -
git pull origin master
: pull remote master branch data to our local master branch -
git checkout -b new-branch-name
: create a new local branch and move to that branch -
git branch
: sanity check that we're in proper new branch - Make code changes
-
git status
: shows what files have had changes made & shows whether our files have been staged or not (green for yes, red for no) -
git add filePath/wanting/toStage.txt
: add files, via their file paths, to the staging/index area -
git status
: sanity check that only preferred files are staged/added to index -
git commit -m "any commit message"
: snapshot currently staged changes via a singular commit & write concise message -
git log
: view our commit history to sanity check that our most recent commit is at the top of the history list -
git push origin new-branch
: push our local new-branch and its data to the remote space (Github) - Create pull request on Github
-
git branch
: sanity check that current branch is still new-branch -
git pull origin new-branch
: pull (to our local new-branch) any changes that might have been added from the remote new-branch - (a) If making changes to the same branch, repeat steps 6-12 (b) If making changes to a different branch, repeat steps 5-12
Top comments (0)