untracked files: (use "git add ..." to include in what will be committed)
Anybody says you should learn Git—and y'all should—but let'due south be honest: Git is kind of hard.
Even almost 10 years into my software development career, I am still learning about the underlying Git fundamentals and how to use Git more than effectively.
Information technology wasn't as well long agone that I realized I had a key misunderstanding of a key control I'd used countless times.
Like many other areas in programming, I believe the best way to larn is to just offset doing.
Simply start being productive with the tool—the fundamentals and edge cases will go sorted out over time.
Then in this tutorial that's exactly what we'll do. We'll work through a series of examples to build a from-the-ground-upward understanding of how to use Git and ultimately collaborate with your teammates.
In doing so, we'll use uncomplicated commands and explicate the underlying concepts as they're useful—merely merely to the extent that they aid understanding.
There's definitely a lot more to Git than is presented here, but these are things you lot'll learn as y'all work with it over time.
I as well will not be using any tree diagrams (like the one beneath) because they just misfile me, and I've never had to think nearly Git in this manner to be productive every bit a software developer.
Here's what we'll cover. Don't let this list intimidate y'all, we'll go stride by step.
- Installing git and setting upwardly a GitHub account
- How to create a new repository in GitHub
- Cloning the repository
- Git branches
- How the bank check the status of a Git project
- How to brand our first commit
- How to push upward our get-go commit to GitHub
- How to add another commit in Git
- How to phase changes in Git
- How to view the Git unequal
- How to collaborate with others in Git
- Feature branches in Git
- Git workflows for collaboration
- How to merge a co-operative in Git
- Pull request workflow
- How to bring our local up to date
- How to retrieve remote data
- How to fix merge conflicts in Git
- Review: how to start a new characteristic workflow
- Conclusion
So with all of that said, I encourage you to follow along with the examples on your own car—permit'southward start!
How to install Git and fix a GitHub business relationship
Showtime, some irksome stuff we demand to do to get upwards and running.
If y'all already accept Git installed, have made a GitHub account (or use whatsoever other provider like GitLab or Bitbucket), and you have setup an SSH key, you tin can skip this section.
If not, y'all'll first need to install Git.
Secondly, we'll be using GitHub in this tutorial, so signup for a GitHub account here.
Subsequently you take a GitHub business relationship, you'll demand to create an SSH key to button your code from your local machine to GitHub (this key proves to GitHub when you lot push lawmaking that you are "you").
It'south not difficult—just follow the steps here.
How to create a new repository in GitHub
The adjacent matter nosotros'll practise is create a new repository in Github.
It's unproblematic. Just click the "New" repository button on your dwelling house page:
Adjacent, choose a name for the repository and whether y'all want the repo to be public or individual. You can optionally add a README file if you lot'd like, and so click "Create repository."
I've called my repository applied-git-tutorial. This repo has all of the finished steps of this tutorial already in information technology, so if you lot want to you can always apply information technology as a reference.
How to clone a Git repository
To start, we'll "clone" the repo. Cloning a repo ways downloading all of the projection's code and metadata from the source—which in this case is GitHub.
To clone a repo, we employ git clone <URL>
.
I used the URL from the repo I just created, merely you should use the URL of your own repository:
$ git clone git@github.com:johnmosesman/practical-git-tutorial.git Cloning into 'applied-git-tutorial'... remote: Enumerating objects: 6, done. remote: Counting objects: 100% (6/6), done. remote: Compressing objects: 100% (iii/three), done. remote: Total 6 (delta 0), reused 0 (delta 0), pack-reused 0 Receiving objects: 100% (6/6), done.
Note: commands to be run in your terminal will be prefixed with a $
.
We'll become into more detail nearly what git clone
does soon, only for now just know that it downloads the project and places it in a folder in your current working directory.
Side by side let'due south change into the new directory using cd
:
$ cd practical-git-tutorial/ /applied-git-tutorial (main)$
We've inverse into the binder (which is just like any other folder), and your concluding may show yous something aslope the directory proper name: (main)
.
Git branches
This (main)
ways that we are currently on a branch called main
. Y'all tin think of a Git branch equally a copy of the project at a specific signal in time that can exist changed independently of other branches.
For case, if we used Git to track writing a book, we might have branches that look like this:
-
master
branch -
table-of-contents
branch -
chapter-1
branch -
chapter-ii
branch - etc.
The main
branch is, well, the "main" branch—the identify where we're going to combine all of the contents of the book into one finalized, finished book.
Nosotros tin can create other branches to carve up and runway specific pieces of work.
If I was working on Chapter 1 and you were working on Chapter 2, we could create two difference branches, chapter-ane
and chapter-2
—effectively two dissimilar copies of the electric current status of the book.
We could and so both work on our respective chapters without stepping on each others' toes or changing the contents out from under each other—we both accept our own working copy that are dissever from each other.
When either of us are finished with our chapter, nosotros can add together the contents of our affiliate co-operative back into the main
branch. When we're both finished, the main
branch will contain both Chapter 1 and Chapter ii.
All the same, in that location are times where you will overwrite or alter the same piece of content equally someone else and we'll have to figure out how to settle those differences—and nosotros'll see that soon.
Annotation: depending on the projection you may meet a branch namedmaster
instead ofmaster
. It doesn't take any functional departure, just blazonmaster
vsprimary
depending on what'due south in your project.
How to check the status of a Git project
One thing we'll do frequently is check the status of our project. What changes accept been fabricated and what practise we want to do with them?
To view the condition of our project we use git status
:
(principal)$ git status On branch master Your branch is up to date with 'origin/chief'. nothing to commit, working tree clean
There's a few things in the outcome of this command, and so let's intermission those downwardly.
The commencement thing git status
tells u.s.a. is we're on the primary
branch:
On branch main
The second sentence is a piddling more than interesting:
Your branch is up to date with 'origin/main'.
Git is telling us that our branch is "up to date" with something called origin/main
.
origin
is a new concept known as a remote. A remote is a "remote source" different from your local machine.
In this projection we have our local copy of the projection, but we tin also add remote sources that we can collaborate with. After all, that is one of the biggest benefits of Git: controlled collaboration with others.
Continuing with our volume-writing example, if I write Chapter 1 on my auto and you write Affiliate 2 on your car, nosotros could both add each other's computers as "remotes" and ship and receive changes from each other.
In practice, the programming customs at large has decided that information technology is all-time to have a single source of truth for lawmaking. One place that is always "correct" well-nigh what the current state of the codebase is. By convention, we phone call this identify the origin.
In this instance, GitHub is our "origin."
In fact, we can see this by running the command git remote -v
(-v
for "verbose"):
(main)$ git remote -v origin git@github.com:johnmosesman/applied-git-tutorial.git (fetch) origin git@github.com:johnmosesman/applied-git-tutorial.git (push)
This command lists all of our remotes. From the outcome we can run across that we accept a remote named origin
, and the Git URL of this remote points to our repo on Github.com. This remote was automatically setup for us when nosotros ran git clone
.
And so coming back to this argument in the consequence of git status
:
Your branch is upwards to date with 'origin/primary'.
When we asked for the condition of our project, Git told us that our local main
branch is up to date with the principal
branch at our origin—which is GitHub.
In fact, git clone
automatically created a main
branch for usa locally because it saw that the origin we cloned from had a branch called master
as its primary branch.
Basically, there are no changes on our local motorcar unlike from GitHub or vice versa—our local main
co-operative and the GitHub master
branch are identical.
As we make changes nosotros'll see this message change to reflect the differences in our local repository and the origin (GitHub) repository.
The final message from git status
is about the land of the local project:
nothing to commit, working tree make clean
Nosotros'll go into more detail hither equally nosotros make changes, but this message is basically saying we haven't done anything—so no changes to report.
To summarize the consequence of git status
:
- We're on branch
main
- Our local
main
branch is identical to theorigin
's (GitHub's)main
branch - We haven't fabricated whatsoever changes to the project yet
How to make our beginning commit
At present that we understand the initial land of our project, permit's make some changes and expect at the result.
Continuing with our book analogy, permit'south make a new file called chapter-1.txt
and insert a judgement into it.
(You tin use the terminal commands beneath, or create and edit the file in any text editor you choose—it doesn't matter.)
(main)$ impact chapter-1.txt (chief)$ echo "Chapter one - The Start" >> affiliate-one.txt (master)$ cat chapter-i.txt Affiliate i - The Kickoff
The commands above make a new file called affiliate-1.txt
using impact
, insert the sentence "Chapter i - The Commencement" using echo
and the >>
operator, and, to double-check our work, show the contents of the file using cat
.
The result is a simple text file with one sentence in it.
Permit's run git status
again and see the difference in its output:
(master)$ git status On co-operative main Your branch is up to date with 'origin/main'. Untracked files: (utilise "git add together <file>..." to include in what will exist committed) chapter-1.txt zip added to commit just untracked files nowadays (use "git add" to track)
Here we run into a dissimilar output than earlier. We see a section describing "Untracked files," and our new file chapter-1.txt
is listed there.
Before Git volition start tracking changes to a file we start take to tell Git to track it—and equally the bottom of the message states—we can apply git add
to practise that:
(main)$ git add together chapter-one.txt
(Instead of specifying the name of the file for git add
, y'all can use a flow (.
) to add all of the changes in the directory.)
Let's check the status again:
(principal)$ git status On co-operative master Your branch is upwards to date with 'origin/chief'. Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: chapter-1.txt john:~/code/practical-git-tutorial (main)$
The bulletin has changed again. Information technology nows says that we have some changes that are ready to be "committed."
A commit in Git is a saved chunk of work, but it's a little unlike from the same save you lot would utilize to relieve a text file in a text editor.
You lot can recollect of a commit every bit a completed idea or unit of work.
For example, if we were continuing to write the contents of Chapter 1 in the book, information technology might look like this:
- Write the title of the chapter. *click save in our editor*
- Write the get-go paragraph of the chapter. *click save in our editor*
- Write the second paragraph of the chapter. *click save once again*
- Write the last paragraph of the chapter. *click save again*
Here, we've "saved" the document four times, but at the end of those 4 saves we now have the outset draft of our chapter, and that draft is one "unit of measurement of work."
Nosotros want to save this file on our calculator, but we besides want to signify that this is a unit of measurement of completed piece of work—even if information technology'southward merely a draft. It'south a chunk of piece of work worth holding onto. We may want to render to it in the hereafter, become dorsum and edit it, or merge this draft into the electric current typhoon of the entire book.
To do this, we create a new commit to signify this milestone. Each commit gets its ain unique identifier, and the order of the commits are preserved.
To commit our changes, they must get-go be added to the staging area by using git add
.
(We'll talk more than nigh the staging area before long.)
Next, we need to finalize the commit by using git commit
.
It's best practice to provide a detailed message of what changes you made—and more importantly—why you are committing these changes.
In one case the commit history becomes hundreds or thousands of commits long, it becomes nigh impossible to understand why a alter was made without a good commit message. Git will show us what files changed and what the changes were, simply the pregnant of those changes is up to us to provide.
Allow's commit the new file nosotros made with a commit message by using the -k
or "bulletin" flag:
(main)$ git commit -m "New chapter ane file with chapter heading" [main a8f8b95] New chapter ane file with chapter heading 1 file changed, ane insertion(+) create style 100644 affiliate-one.txt
We've now committed that chunk of work, and we can see that by viewing the Git log via git log
:
(master)$ git log commit a8f8b95f19105fe10ed144fead9cab84520181e3 (HEAD -> main) Author: John Mosesman <johnmosesman@gmail.com> Date: Fri Mar 19 12:27:35 2021 -0500 New affiliate 1 file with chapter heading commit 2592324fae9c615a96f856a0d8b8fe1d2d8439f8 (origin/main, origin/Caput) Author: John Mosesman <johnmosesman@users.noreply.github.com> Date: Wednesday Mar 17 08:48:25 2021 -0500 Update README.dr. commit 024ea223ee4055ae82ee31fc605bbd8a5a3673a0 Author: John Mosesman <johnmosesman@users.noreply.github.com> Engagement: Wed Mar 17 08:48:10 2021 -0500 Initial commit
Looking at this log, we see that at that place are 3 commits in the project history.
The latest commit is the one nosotros just made. We can see the aforementioned commit message we but used: "New affiliate 1 file...".
There are too ii previous commits: 1 when I initialized the projection and some other when I updated the README.md
file on GitHub.
Detect that each commit has a long string of numbers and characters associated with it:
commit a8f8b95f19105fe10ed144fead9cab84520181e3 (HEAD -> master)
This string of characters and numbers is chosen the SHA—it's the unique ID generated past a hashing algorithm for this commit. Just take note of these for now—we'll come back to this before long.
We also see two other interesting things in the log after the commit SHAs:
-
(HEAD -> principal)
side by side to our latest commit - And
(origin/master, origin/Caput)
next to the commit before that 1.
This data tells united states the current status of our branches and remotes (equally far as nosotros know—but more on this later).
For the latest commit, nosotros meet that the Head
(aka "where nosotros are at present" in the projection history) is pointing at our local main
branch—represented by HEAD -> master
.
This makes sense because we just made that commit, and nosotros haven't done anything else—nosotros're nevertheless at the indicate in fourth dimension where we made that commit.
If we look at the previous commit starting with 25923
, we come across (origin/main, origin/HEAD)
. This tells us that, on the origin (aka GitHub), GitHub's Caput
or "current identify" is on our previous commit.
Basically, our local machine thinks the latest change for local master
branch is the commit where we added Chapter ane, and our local machine likewise thinks that on GitHub the latest change is the commit where I updated the README before I wrote this mail.
And this makes sense—nosotros oasis't told GitHub about the newest commit we made. GitHub however thinks that the repo is upwardly to date with what it has seen.
Now let'due south push button upwardly our new commit to GitHub.
How to push button upwards our first commit to GitHub
Nosotros have a new commit on our local machine and we demand to update our "source of truth"—the origin
remote—aka GitHub.
We're currently on the main
co-operative locally, so nosotros need to tell GitHub to update its own master
with the new commit that nosotros fabricated.
To do that we use the git push
control and we can specify where we want to button and what branch we want to push button to.
(main)$ git push origin main Enumerating objects: four, done. Counting objects: 100% (4/four), done. Delta compression using upward to 16 threads Compressing objects: 100% (2/2), done. Writing objects: 100% (3/3), 326 bytes | 326.00 KiB/s, done. Total 3 (delta 0), reused 0 (delta 0) To github.com:johnmosesman/practical-git-tutorial.git 2592324..a8f8b95 principal -> main
Here nosotros pushed to the origin
remote (GitHub) and to the main
branch.
The output tells us about some file operations Git did to do that, and the terminal line of the output tells us which commits it pushed and to where:
To github.com:johnmosesman/practical-git-tutorial.git 2592324..a8f8b95 main -> main
Here it shows united states of america that we pushed our main
co-operative to GitHub's master
branch.
If nosotros look dorsum at the git log
output we'll notice that both our local and origin
betoken to the aforementioned commit now:
(main)$ git log commit f5b6e2f18f742e2b851e38f52a969dd921f72d2f (Caput -> primary, origin/main, origin/HEAD) Author: John Mosesman <johnmosesman@gmail.com> Appointment: Monday Mar 22 10:07:35 2021 -0500 Added the intro line to chapter 1
In short, on origin
(GitHub) the main
branch (also written every bit origin/main
) has now placed our new commit as the latest commit in the history.
If nosotros were working with other collaborators, they could now pull down our newest change from GitHub and begin editing the Chapter 1 as well.
How to add some other commit in Git
Before we offset collaborating with others, allow's make another small modify to meet what happens when nosotros edit an existing file.
Let's add another line into our Chapter ane file:
(main)$ echo "Information technology was the best of times, it was the worst of times" >> chapter-1.txt (main)$ cat chapter-1.txt Chapter one - The Beginning It was the best of times, information technology was the worst of times
Using true cat
we can run into that our file at present contains two lines.
Let's look at the status of our Git repo once more:
(chief)$ git status On co-operative main Your co-operative is upward to date with 'origin/main'. Changes not staged for commit: (apply "git add <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) modified: chapter-1.txt no changes added to commit (utilize "git add together" and/or "git commit -a")
Starting from the pinnacle, we'll notice the output says Your branch is up to date with 'origin/principal'.
This might seem odd to you since we just changed a file, but Git is only comparison the commits nosotros've made confronting the commits in origin/main
.
The next section of the output explains information technology a trivial more than:
Changes not staged for commit: (use "git add <file>..." to update what will be committed) (utilise "git restore <file>..." to discard changes in working directory) modified: chapter-1.txt
Here Git tells united states of america that we take "changes non staged for commit."
Before we can commit a set of changes, nosotros get-go have to stage them.
How to stage changes in Git
To illustrate the usefulness of the staging surface area, let's first stage our changes by using git add
:
(main)$ git add . (main)$ git status On branch principal Your co-operative is upward to date with 'origin/principal'. Changes to exist committed: (use "git restore --staged <file>..." to unstage) modified: affiliate-1.txt
These changes are now ready to be committed, only before we commit them let'due south add some other change into our chapter-1.txt
file.
I'm going to supplant the contents of affiliate-1.txt
entirely with new text:
Annotation: I'one thousand using>
hither instead of>>
which volition replace the contents of the file instead of appending to the file.
(main)$ repeat "New file contents" > chapter-i.txt (main)$ cat chapter-1.txt New file contents (primary)$ git status On branch main Your co-operative is up to date with 'origin/primary'. Changes to exist committed: (use "git restore --staged <file>..." to unstage) modified: chapter-i.txt Changes not staged for commit: (use "git add <file>..." to update what will be committed) (utilize "git restore <file>..." to discard changes in working directory) modified: chapter-1.txt
From the output we can encounter that we at present have staged changes, and not staged changes.
While the file itself can just comprise one matter, Git keeps rails of both changes for usa—even though they're changes to the same lines!
Even so, from the output above we can't really tell what those changes were—we merely know that they be.
To view these changes, we'll outset wait at the command line manner (which I never use), and so a style that uses a GUI (which is 100% nicer).
How to view the Git diff
To view the changes, we demand to look at the Git diff.
A diff (brusk for difference) is the deviation between two sets of changes. Those changes could be anything from staged changes to not-staged changes to commits.
The control line manner to do this is by using git diff
.
We'll look at this output in our simple case here simply for completeness' sake. But, as I mentioned before, nosotros're interested in effective Git workflows, and once y'all get to changes of any decent size across multiple files this command line output simply becomes not constructive.
But for completeness, here it is:
(main)$ git unequal diff --git a/chapter-1.txt b/chapter-i.txt index 0450d87..4cbeaee 100644 --- a/chapter-1.txt +++ b/chapter-1.txt @@ -i,2 +one @@ -Chapter 1 - The Beginning -It was the best of times, it was the worst of times +New file contents
My terminal attempts to colorize this output to help with readability, but the of import parts to detect here is it tells united states what file nosotros're diffing, affiliate-one.txt
, and at the bottom it shows us the actual differences. Let'south fundamental in on those lines:
-Chapter 1 - The Kickoff -It was the best of times, information technology was the worst of times +New file contents
The lines starting with a minus sign (-
) are lines we deleted entirely or in part, and the lines starting with a +
sign represent lines added entirely or in part.
At present, with multiple files and many lines changed this output becomes unwieldy—fast. There is a better way, and even almost ten years into my programming career I still use a simple GUI program to help look at and manage diffs.
The program I employ is called GitX, and information technology'south an quondam and outdated piece of software that'southward not even really being maintained anymore. Still, I but apply it to view and manage file diffs—so it works for me.
I wouldn't particularly recommend this one, merely it is free. Although I've never used it, the GitHub Desktop client is probably a expert pick.
Now with that little aside out of the way, here'south what the unequal looks similar in my tool.
To start, the staged changes on the right-mitt side bear witness our original add together of the second judgement:
In the unstaged changes on the left-hand side, we run across the removal of those ii lines entirely and the addition of a new line:
This corresponds to the file replace command we ran.
It is and so much easier to understand the diff in a GUI program. This program also allows me to quickly switch between staging and un-staging files by just dragging them around. I tin can even stage or united nations-stage individual lines in a file dorsum and along as well.
At that place's no bonus points for using the command line vs a GUI program. Use whatever gets the task done for you.
Now that we've seen how the staging surface area and Git diffs piece of work, let's discard our non-staged changes and then nosotros can get back to committing our first change.
In my GUI plan I can right-click the file and click "Discard changes", simply I'll show the command line version hither as well.
The output of our final git status
actually showed us how to do this by using git restore
. Nosotros can pass the file path or merely a .
for the whole directory:
(principal)$ git restore .
If we check the status again nosotros're back to just our staged changes, and we tin continue.
Note: Git only commits changes that are staged, so we could have left those unstaged changes in our working directory and it wouldn't interfere with the committing process.All the same, it would make our future changes more than cumbersome to deal with—so it makes sense to discard those changes to keep our working directory in good shape.
Now allow'southward finally commit these changes with a message nigh what we did:
(main)$ git commit -m "Added the intro line to chapter 1" [primary f5b6e2f] Added the intro line to chapter i 1 file changed, 1 insertion(+)
Checking the condition once once again shows us that our branch is "ahead of 'origin/main' by i commit":
(main)$ git condition On branch principal Your branch is alee of 'origin/primary' by 1 commit. (use "git button" to publish your local commits) nothing to commit, working tree clean
Finally allow's push upwardly our change:
(main)$ git button origin primary
How to collaborate with others in Git
So far we've been looking at the simplest use case: working by ourselves on i co-operative.
In reality, we'll usually be working with multiple people working on multiple unlike branches. This is the real power of Git subsequently all: a organisation to interact and rail changes over fourth dimension amongst many collaborators.
For now, let's continue working as if nosotros're the only person on the projection, but let's adjust our workflow a niggling bit to set for when that's not the instance.
In general, information technology'due south best do to not piece of work direct on the chief
branch.
The principal
branch is supposed to be the "source of truth" for the project—changes to it should exist advisedly reviewed. Any change in origin/principal
becomes the new "source of truth" for anyone else working on the project, and so nosotros shouldn't merely change information technology without some thought and review by others.
Instead of working on main
straight, let'due south co-operative off of primary
into our own feature branch, and then merge those changes back into main
.
That'south a lot of new terminology, and then permit'south take it one step at a time.
Characteristic branches in Git
To begin, permit's branch off of main
and create our own characteristic branch to work on.
When yous create a co-operative off of some other branch, you create a re-create of that branch at that indicate in time. You can now change this new branch independently of the original branch.
To try this out, let's brand a new branch called chapter-ii
. To do this we employ git checkout
with the -b
flag and the proper noun we want the new branch to take:
(main)$ git checkout -b chapter-2 Switched to a new branch 'chapter-2' (affiliate-2)$
Discover that the terminal now shows us on the affiliate-2
branch. Changes on the chapter-2
branch will non touch on the main
branch at all. Nosotros essentially have a new playground to make whatsoever changes nosotros want to make without affecting chief
.
At that place are interesting things happening under the hood here, simply for the purpose of this tutorial we just need to know that to "checkout" something in Git means to "change my local projection to look exactly like the projection looked at some specific signal in fourth dimension." You can think of a branch every bit a pointer to a specific timeline of the Git history.
There's a lot more happening here, but that definition should exist expert enough for now.
So nosotros have a new co-operative, and for now that new branch is identical to main
(we oasis't made any changes notwithstanding).
Next permit's repeat what we've already done before and create a new file chosen chapter-2.txt
, requite it some content, and commit it:
(affiliate-2)$ impact affiliate-2.txt (chapter-ii)$ repeat "Chapter two - The next affiliate" >> chapter-two.txt (chapter-2)$ git status On branch affiliate-2 Untracked files: (use "git add <file>..." to include in what will be committed) affiliate-2.txt zilch added to commit but untracked files present (use "git add" to rails) (chapter-2)$ git add . (chapter-ii)$ git commit -m "Creates chapter ii and adds the topic sentence" [chapter-2 741822a] Creates chapter 2 and adds the topic sentence i file changed, 1 insertion(+) create fashion 100644 affiliate-2.txt
Nothing new in there—only the same affair we did for Chapter 1.
At present that nosotros take a new commit on our chapter-2
branch, permit's look the Git log and compare this new branch to main
:
(chapter-two)$ git log commit 741822a9fd7b15b6e3caf437dd0617fabf918449 (Head -> affiliate-2) Author: John Mosesman <johnmosesman@gmail.com> Appointment: Monday Mar 22 10:33:26 2021 -0500 Creates affiliate two and adds the topic sentence commit f5b6e2f18f742e2b851e38f52a969dd921f72d2f (origin/principal, origin/HEAD, principal) Author: John Mosesman <johnmosesman@gmail.com> Date: Mon Mar 22 10:07:35 2021 -0500 Added the intro line to chapter 1 commit a8f8b95f19105fe10ed144fead9cab84520181e3 Author: John Mosesman <johnmosesman@gmail.com> Date: Friday Mar 19 12:27:35 2021 -0500 New chapter one file with affiliate heading ...
We'll notice in the log that our latest commit is shown at the top, and our HEAD
is again different from our origin
. This again makes sense—we've made changes locally that aren't in GitHub.
Now we need to go our new changes into the main
branch.
Git workflows for collaboration
There are a couple of ways to get our new Affiliate two into the main
branch and into GitHub, and the style we choose depends on the projection and what workflow we're using to interact with others.
First allow's talk about a couple different workflows we could use.
The showtime one is the most straightforward:
- Merge changes from
chapter-two
into our localmain
co-operative - Push local
chief
branch toorigin/primary
The second way is a footling more complicated:
- Button our local
chapter-2
co-operative to origin (this creates a new branch onorigin
chosenorigin/chapter-2
) - Merge
origin/chapter-2
intoorigin/main
on GitHub - Pull down the new changes from
origin/main
into our localmain
The first workflow is definitely easier, and it is something I would use if I was working on this projection by myself without any other collaborators.
Nonetheless, if I had collaborators, I wouldn't desire to push straight to the main
co-operative from my local. By doing so I would be irresolute and taking control of the history of the projection solely on my own changes—without any input or review from collaborators.
For this reason, if in that location were multiple people working on the same project, I would employ the 2nd workflow because it is a ameliorate collaboration process for the team.
That beingness said, we'll get over both workflows, and allow's start with the showtime ane which is less complicated.
How to merge a co-operative in Git
When y'all desire to combine the contents of two branches into ane in Git, there are a few methods of doing and then. The beginning and probably simplest way is to do a merge.
A merge, like it sounds, tries to take the contents of ane branch and apply (or "merge in") those changes into some other branch.
In our scenario, nosotros desire to accept the contents of the affiliate-2
branch and merge them into main
. Said another manner, we want to take the current land of principal
and add in our changes from the chapter-2
branch.
We tin can do this by using git merge
, and we'll look at the outcome of it later on.
The outset thing we need to do is exist on the primary co-operative that we want to merge changes into. Since we desire main
to absorb the changes from affiliate-2
, nosotros showtime need to be on the main
branch.
To switch dorsum to the principal
branch, we can again utilize git checkout
and specify the branch name of principal
. This time we don't utilize the -b
flag considering nosotros want to switch to an existing co-operative and non create a new 1:
(affiliate-2)$ git checkout main Switched to branch 'primary' Your branch is up to engagement with 'origin/main'. (main)$
Nosotros're now back on the chief
branch, and we get a quick status message saying nosotros're up to appointment with origin/main
.
Next, let'south merge our chapter-2
branch into master
:
(main)$ git merge chapter-2 Updating f5b6e2f..741822a Fast-forward chapter-2.txt | i + 1 file inverse, 1 insertion(+) create style 100644 chapter-2.txt
Let's await at the Git log once more to come across the effect:
(main)$ git log commit 741822a9fd7b15b6e3caf437dd0617fabf918449 (Caput -> master, chapter-2) Author: John Mosesman <johnmosesman@gmail.com> Appointment: Mon Mar 22 10:33:26 2021 -0500 Creates affiliate 2 and adds the topic sentence commit f5b6e2f18f742e2b851e38f52a969dd921f72d2f (origin/principal, origin/Caput) Author: John Mosesman <johnmosesman@gmail.com> Date: Mon Mar 22 10:07:35 2021 -0500 Added the intro line to chapter i ...
We can see that our main
branch at present contains the new commit from affiliate-ii
, and that our origin
is still at the previous commit (as we oasis't updated origin
yet).
Finally, let's push button our changes up to origin/main
:
(primary)$ git push button origin chief Full 0 (delta 0), reused 0 (delta 0) To github.com:johnmosesman/applied-git-tutorial.git f5b6e2f..741822a master -> master
Nosotros've successfully merge our chapter-2
co-operative, and pushed that change upwards to GitHub!
Every bit a last cleanup stride, let'south delete the affiliate-2
characteristic branch as information technology has already been merged into main
:
(main)$ git branch -d chapter-2 Deleted co-operative affiliate-2 (was 741822a).
Note: thegit branch
command without a co-operative proper noun argument will list all of the branches yous accept locally.Adding the
-d
flag and a branch proper name deletes the branch passed in.
Pull asking workflow
To work through our collaboration workflow, let's echo the same matter we've done with Chapter 1 & 2 on a new branch called chapter-3
:
(Now would be a practiced time to try this on your own!)
(main)$ git checkout -b affiliate-3 (affiliate-3)$ touch affiliate-3.txt (chapter-3)$ echo "Chapter 3 - The End?" >> affiliate-3.txt (affiliate-3)$ git add . (chapter-3)$ git commit -m "Adds Chapter 3"
At present we have a new commit on a new branch called affiliate-3
.
Let'south review how we're going to get this new co-operative merged into master
without acting directly on main
ourselves:
- Push our local
chapter-three
branch to origin (this creates a new branch onorigin
chosenorigin/chapter-three
) - Merge
origin/chapter-3
intoorigin/principal
on GitHub - Pull down the new changes from
origin/master
into our localmain
A couple more steps—but none that are too complicated.
The first pace is to push button our new co-operative to GitHub. Since this branch doesn't exist nevertheless on GitHub, GitHub will make a new co-operative for us that is a copy of what we pushed:
(chapter-iii)$ git push origin chapter-3 Enumerating objects: 4, done. Counting objects: 100% (4/4), done. Delta compression using up to xvi threads Compressing objects: 100% (2/2), washed. Writing objects: 100% (three/three), 299 bytes | 299.00 KiB/s, done. Total 3 (delta 1), reused 0 (delta 0) remote: Resolving deltas: 100% (one/1), completed with 1 local object. remote: remote: Create a pull asking for 'chapter-three' on GitHub by visiting: remote: https://github.com/johnmosesman/applied-git-tutorial/pull/new/affiliate-3 remote: To github.com:johnmosesman/practical-git-tutorial.git * [new branch] affiliate-3 -> chapter-3
Now that we have our co-operative on GitHub, we tin can create a pull request to be reviewed past our teammates.
GitHub even provides us with the URL to visit in our output higher up: https://github.com/johnmosesman/applied-git-tutorial/pull/new/chapter-iii
A couple notes: this next part shows GitHub's UI and process for pull requests, just this process should exist very similar for other services (like GitLab, Bitbucket, etc.).Also go along in mind I'm using my own repo, then some of the URLs you encounter here will be different from yours.
Visiting the URL above, nosotros go far at a page to open a new pull request.
We come across a few things:
- A place to specify the proper noun of the pull request (a topic sentence to easily sympathize what this PR is about)
- A box for a description to explicate the changes nosotros made and whatever other context we want to provide (you can as well add images, gifs, or videos here equally well)
- And beneath all of that is the list of files we changed and the changes in them (the diff).
Discover that the UI shows base: main <- compare: affiliate-3
. This is GitHub telling us that we're setting the pull request to merge chapter-three
into principal
.
Below the pull request description is the diff of the changes nosotros fabricated:
We'll find that merely the file chapter-three.txt
is shown, and this is because information technology'due south the merely file that nosotros changed.
There are other files currently in our project (affiliate-1.txt
, chapter-two.txt
), but those files didn't change and so in that location'due south no need to testify them.
Nosotros meet the one line nosotros inserted into affiliate-3.txt
—signified by a +
sign at the start of the line and the greenish background which signifies an addition to the file.
Later clicking "Create Pull Request" we're taken to the new PR we just fabricated.
At this signal we could assign a reviewer to the PR and have a back-and-forth discussion effectually the lawmaking past leaving comments on specific lines in the unequal. After the code has been reviewed and we make any changes that demand to be made, nosotros're ready to merge.
For this sake of this tutorial we'll skip the review process, and merely click the big green merge button:
And with that, our pull asking has been merged into main
!
How to bring our local up to date
We've at present made a change to origin/main
in a safe, controlled, and peer-reviewed style.
But, our local doesn't know annihilation virtually this change. Locally, Git nonetheless thinks we're on our chapter-3
co-operative which isn't merged into main
:
(chapter-three)$ git log commit 085ca1ce2d0010fdaa1c0ffc23ff880091ce1692 (HEAD -> chapter-iii, origin/affiliate-iii) Writer: John Mosesman <johnmosesman@gmail.com> Date: Tue Mar 23 09:19:14 2021 -0500 Adds Chapter three commit 741822a9fd7b15b6e3caf437dd0617fabf918449 (origin/chief, origin/Head, main) Author: John Mosesman <johnmosesman@gmail.com> Date: Mon Mar 22 10:33:26 2021 -0500 Creates chapter 2 and adds the topic judgement ...
Our local shows origin/chief
on the previous commit starting with 741822
. Nosotros need to pull in the new information from our origin
to update our local repository.
How to retrieve remote data
As with many other things with Git, at that place are many dissimilar methods to reach the same chore.
For our purposes, nosotros'll await at a straightforward style that will work in the majority of cases.
To kickoff, let'due south switch back to our main
co-operative locally:
(affiliate-3)$ git checkout main Switched to branch 'main' Your co-operative is up to date with 'origin/primary'.
Our local thinks we're up to appointment with origin/chief
considering we oasis't asked the remote repository (origin
) for new data since we pulled the project at the beginning using git clone
.
Git repositories are not live-updating—they're just a snapshot of the history at a indicate in fourth dimension. To receive any new data near the repository nosotros have to ask for it once again.
To recollect any new information that has changed on the remote, we utilize git fetch
:
(main)$ git fetch From github.com:johnmosesman/practical-git-tutorial 741822a..10630f2 main -> origin/main
The output shows us that origin/chief
is now pointing to a commit starting with 10630f2
. This commit prefix matches the SHA of the merge commit of our pull asking.
At that place are a few ways to merge 2 branches into i another, and one of those means is by creating a merge commit. That's what happened here.
Our local repository now knows about the presence of these new commits, simply nosotros oasis't done anything with them yet.
Running git fetch
doesn't actually change any of our files—it just downloads new information from the remote nigh the condition of the repo.
Now that our local repository is enlightened of the status of each branch (but hasn't changed or updated any of the branches), let's check our condition again:
(main)$ git status Your branch is behind 'origin/main' by 2 commits, and can exist fast-forwarded. (employ "git pull" to update your local co-operative)
Our local now knows that our local primary
is backside origin/master
past 2 commits (the commit from the chapter-iii
branch and the PR merge commit).
It besides gives us the hint to use git pull
to update our local branch:
john:~/code/practical-git-tutorial (main)$ git pull origin chief From github.com:johnmosesman/practical-git-tutorial * branch master -> FETCH_HEAD Updating 741822a..10630f2 Fast-forward chapter-three.txt | 1 + 1 file changed, i insertion(+) create style 100644 chapter-3.txt
The git pull
command is actually a shorthand for running two commands: git fetch
followed by a git merge
.
Since git fetch
doesn't apply any changes locally, it tin can be useful to use git fetch
to come across if our branches are up to appointment with the remote (possibly we don't want to merge in the changes withal), or to pull down new branches that exist on the remote and not on our local motorcar.
Fetching a new branch from a remote will go alee and download that branch also to your local machine—since information technology'south a new co-operative information technology won't conflict with anything in your local setup.
Nosotros could accept just done a git pull
initially instead of starting time doing a git fetch
, but I wanted to explain git fetch
equally information technology is useful in its ain correct.
After running git pull
, if we run git status
one time again we'll see that everything is up to date.
And with that, we've pulled in changes from our remote and got our local up to date!
How to fix merge conflicts in Git
The final topic we'll cover is how to bargain with conflicts.
So far, Git has just magically handled all of the file updating, and most of the fourth dimension Git tin merely handle it. But, there are times when Git doesn't know how to combine changes together, and that creates a disharmonize.
A conflict occurs when merging two changes that have changed the same line in a file. If two commits accept changed the same line in a file, Git doesn't know which commit's changes to use, and information technology volition require you to brand the choice.
To setup this scenario, I've created some other branch on Github called chapter-3-collaboration
. Let'south imagine that a teammate has already started working on this branch and they've asked you to collaborate with them in finishing out Chapter 3.
Since this is a new branch that we don't take locally, nosotros tin can apply git fetch
to call back the new branch data from the remote, and then switch to that branch using git checkout
:
(main)$ git fetch From github.com:johnmosesman/practical-git-tutorial * [new co-operative] chapter-3-collaboration -> origin/chapter-3-collaboration (primary)$ git checkout chapter-three-collaboration Branch 'chapter-3-collaboration' fix up to track remote branch 'chapter-3-collaboration' from 'origin'. Switched to a new branch 'affiliate-3-collaboration' (chapter-3-collaboration)$
We've now pulled downward the new branch to our local repository and switched to it. This is the contents of chapter-3.txt
on this new branch currently:
(affiliate-3-collaboration)$ cat chapter-3.txt Chapter 3 - The End? This is a sentence.
It's a title and i sentence. Permit's change the title to something new similar "Chapter 3 - The End Is Only The Commencement."
The contents of chapter-3.txt
now look like this:
(chapter-3-collaboration)$ cat chapter-3.txt Chapter 3 - The Finish Is Just The Beginning This is a sentence.
After committing that change, if we try to push button it upwards nosotros become this message:
(chapter-3-collaboration)$ git push button origin chapter-3-collaboration To github.com:johnmosesman/practical-git-tutorial.git ! [rejected] chapter-3-collaboration -> chapter-3-collaboration (non-fast-forward) error: failed to button some refs to 'git@github.com:johnmosesman/practical-git-tutorial.git' hint: Updates were rejected because the tip of your current branch is behind hint: its remote counterpart. Integrate the remote changes (due east.g. hint: 'git pull ...') before pushing again. hint: See the 'Note virtually fast-forwards' in 'git button --help' for details.
Our teammate has already made some commits before nosotros did, and pushed it to the remote branch. Our local branch is now out of date with the remote, and GitHub is denying our button until we merge in the changes from our teammate:
... the tip of your electric current co-operative is behind its remote counterpart. Integrate the remote changes ... before pushing over again.
It also gives us a hint about how to do that: git pull
.
(chapter-3-collaboration)$ git pull origin chapter-iii-collaboration From github.com:johnmosesman/applied-git-tutorial * branch chapter-iii-collaboration -> FETCH_HEAD Auto-merging chapter-3.txt CONFLICT (content): Merge conflict in chapter-iii.txt Automatic merge failed; fix conflicts and then commit the result.
Later pulling—and every bit we might have expected given the topic we're currently discussing—we have a merge conflict.
Git tried to automatically merge our teammate'south changes into ours, but there was a identify in the file that it couldn't automatically merge—we both changed the same line.
Git stopped "mid-merge" and is telling u.s. nosotros need to prepare the merge conflicts before information technology can finish the merge. Let's wait at our git status
currently:
(chapter-three-collaboration)$ git status On branch chapter-three-collaboration Your branch and 'origin/chapter-3-collaboration' have diverged, and have 1 and 1 different commits each, respectively. (utilize "git pull" to merge the remote co-operative into yours) Yous have unmerged paths. (prepare conflicts and run "git commit") (apply "git merge --arrest" to abort the merge) Unmerged paths: (use "git add <file>..." to mark resolution) both modified: chapter-3.txt no changes added to commit (employ "git add together" and/or "git commit -a")
Git tells united states of america our branch and the remote co-operative have 1 commit dissimilar from each other. Information technology as well tells us that we have some "unmerged paths"—that we're currently mid-merge and we demand to gear up the conflicts.
Information technology shows us chapter-3.txt
is currently modified, then let's look at the contents of chapter-3.txt
:
(chapter-iii-collaboration)$ cat chapter-iii.txt <<<<<<< Caput Chapter 3 - The End Is Just The First ======= Chapter 3 - The Cease But Not The Ending >>>>>>> 2f6874f650a6a9d2b7ccefa7c9618deb1d45541e This is a sentence.
Git has added some markers to the file to show us where the conflict happened. Both nosotros and our teammate changed the title judgement, so information technology's surrounded by Git's markers of a disharmonize: <<<
and >>>
arrows separated by a line of ===
.
The pinnacle line, signified by <<<<<<< HEAD
and followed by "Affiliate 3 - The End Is Only The Beginning", is the alter that we merely made. Git is telling usa that this line is where our current Head
is at—i.e., this is the modify at our electric current commit.
The line below it, "Affiliate 3 - The End Merely Not The Ending" followed by >>>>>>> 2f6874f650a6a9d2b7ccefa7c9618deb1d45541e
, is the line and commit from our teammate.
Basically, Git is telling us, "Which ane of these lines (or some combination of these lines) do y'all want to keep?"
Notice that the line at the lesser file isn't wrapped upward in the conflicts—it wasn't inverse by both commits.
We need to resolve the conflict by deleting one of the lines or combining the 2 lines into 1 (and remember to remove all of the extra markers that Git put in in that location as well).
I'm going to accept a combination of these lines, and so the terminal file looks similar this:
(chapter-iii-collaboration)$ cat affiliate-iii.txt Chapter 3 - The End Is Not The Ending--Simply Only The Beginning This is a sentence.
To finish the merge, we just need to commit our disharmonize resolution:
(chapter-3-collaboration)$ git add together . (chapter-3-collaboration)$ git commit -m "Merge new title from teammate" [chapter-3-collaboration bd621aa] Merge new championship from teammate (chapter-three-collaboration)$ git status On branch chapter-three-collaboration Your co-operative is ahead of 'origin/chapter-3-collaboration' by 2 commits. (use "git push" to publish your local commits) zippo to commit, working tree clean
The result of git condition
tells us that our local branch is is ahead of 'origin/chapter-3-collaboration' by ii commits.
.
Looking at the git log
confirms this:
commit bd621aa0e491a291af409283f5fd1f68407b94e0 (Head -> chapter-iii-collaboration) Merge: 74ed9b0 2f6874f Author: John Mosesman <johnmosesman@gmail.com> Date: Thu Mar 25 09:20:42 2021 -0500 Merge new title from teammate commit 74ed9b0d0d9154c912e1f194f04dbd6abea602e6 Author: John Mosesman <johnmosesman@gmail.com> Date: Thu Mar 25 09:02:03 2021 -0500 New title commit 2f6874f650a6a9d2b7ccefa7c9618deb1d45541e (origin/chapter-three-collaboration) Writer: John Mosesman <johnmosesman@gmail.com> Date: Thu Mar 25 08:58:58 2021 -0500 Update title ...
The resulting commit history has both of the commits on the co-operative and our merge commit at the top.
From here, we only need to push up our changes to the remote:
(affiliate-three-collaboration)$ git push origin chapter-3-collaboration Enumerating objects: 10, done. Counting objects: 100% (10/x), done. Delta compression using up to 16 threads Compressing objects: 100% (6/vi), done. Writing objects: 100% (6/6), 647 bytes | 647.00 KiB/s, done. Total 6 (delta 2), reused 0 (delta 0) remote: Resolving deltas: 100% (2/two), completed with one local object. To github.com:johnmosesman/practical-git-tutorial.git 2f6874f..bd621aa affiliate-3-collaboration -> affiliate-3-collaboration
Now that we've changed the remote branch, our teammate would demand to do a git pull
to merge in our new merged changes.
And, ideally we would tell our teammate that we pushed upwards a new change so they could pull it down before they continue editing—reducing the likelihood they'll have to fix a merge conflict in the future, too.
Branches off of branches
We could have also created our own branch off of the chapter-iii-collaboration
branch. This would let us piece of work without having to worry nigh merge conflicts until the very terminate.
Once we had finished our work in our ain carve up branch, we could then merge our feature branch into our teammate's feature branch—and then into main
.
chapter-3-collaboration-john
->chapter-3-collaboration
->main
As yous can run across the branch structure tin can get quite complicated every bit more and more branches branch off of each other and become ahead of and behind each other.
Because of this, information technology's generally a good idea to keep branches modest and isolated and endeavour to merge them apace and often.
This can help avoid a lot of painful merge conflicts.
Review: how to kickoff a new feature workflow
I'll stop with a quick review of how to arroyo starting a new task and the commands and flows to do it.
Say you've been given your first ticket at a new job: a small issues to squash in your team's product.
The beginning affair you'd need to do is pull downwards the repo using git clone <URL>
.
Next, you'd want to make a feature branch off of principal
using git checkout -b <BRANCH_NAME>
. After that, you'd fix the bug and commit the change(s) using git add
and git commit
.
Maybe solving this problem takes multiple commits—or peradventure y'all brand a few commits in an attempt to solve it before you finally get in at the solution. That's ok too.
After committing, you push your new branch to the origin
(git button origin <BRANCH_NAME>
) and create a pull request. Subsequently a code review your branch is merged in (yay!).
You've now completed your characteristic, and it's time to switch back to principal
(using git checkout principal
), employ git pull
to get your latest changes plus whatsoever other changes other people have made, and beginning off again with a new co-operative.
Determination
As mentioned in the beginning, there are many ways to arroyo working with Git and Git workflows.
In that location'south also a lot of underlying Git "magic" (that is, code being run that you don't understand yet), simply you will learn and choice upwards more of this with time.
I spent the first many years of my career just using memorized commands and workflows. It worked. As I ran into problems or collaborated with teammates I learned more and eventually my skill with Git expanded.
In the start, don't make it any harder than it has to be! You lot will acquire over time.
If yous liked this commodity, I write about technical topics like this also equally non-technical topics on my site.
I also write similar things on Twitter: @johnmosesman.
Either way, experience free to send me a message.
Thank you for reading!
John
Learn to lawmaking for gratuitous. freeCodeCamp's open source curriculum has helped more than xl,000 people get jobs as developers. Get started
willinghamjoods1973.blogspot.com
Source: https://www.freecodecamp.org/news/practical-git-and-git-workflows/
0 Response to "untracked files: (use "git add..." to include in what will be committed)"
Post a Comment