Wprowadzenie do GITa (film, 28 minut)
David Mahler przedstawia w swoim filmie wprowadzenie do systemu kontroli wersji Git, koncentrując się na podstawowych pojęciach i terminologii. Zrozumienie tych centralnych koncepcji jest kluczowe przed przejściem do bardziej zaawansowanych tematów, takich jak rozgałęzianie i scalanie, które będą omawiane w następnych filmach. W filmie omówiono diagramy, które pomagają w zrozumieniu działania poleceń Git oraz modelu repozytoriów. W szczególności omówiono diagram grafu commitów oraz trzy obszary koncepcyjne plików w Git, co ułatwia nowe spojrzenie na kontrolę wersji.
Git, jako typ systemu kontroli wersji, pozwala na rejestrowanie zmian w plikach w czasie. Może to dotyczyć różnych rodzajów plików, od dokumentacji po kody źródłowe. David podkreśla, że Git szczególnie dobrze działa z plikami tekstowymi. Przy pomocy Gita można wykonywać takie zadania jak robienie zrzutów plików w czasie czy przywracanie wcześniejszych wersji plików. W filmie przedstawiono również przykłady pracy na wielu wersjach plików równolegle, co może być przydatne podczas dodawania nowych funkcji do kodu.
Tworzenie repozytoriów Git z użyciem komendy git init oraz dodawanie pierwszych plików do repozytoriów to kroki, które David dokładnie przedstawia. Graf commitów ilustruje, że każda zmiana w pliku jest zapisywana w postaci commitów, co umożliwia pełen audyt historii projektu. Użytkownicy mogą przywracać różne wersje plików według potrzeb, co znacząco zwiększa elastyczność projektu, zwłaszcza w złożonych systemach.
David pokazuje również, jak ważne jest skonfigurowanie swojego imienia i adresu e-mail w Git, co jest niezbędne do śledzenia, kto dokonał jakich zmian w projekcie. Systematyzacja procesów dzięki dodawaniu nowych plików lub usuwaniu istniejących przy użyciu poleceń git add i git rm jest kluczowa dla zarządzania projektem. W miarę postępu wideo, David zademonstrował także, w jaki sposób dodawane są pliki do staging area oraz jak można tworzyć commity, korzystając z różnych metod.
Na koniec David podsumowuje film, dokładając, że poprzedni commit pokazuje pełną historię zmian, a różne powody do używania pliku .gitignore są również wyjaśnione. Na chwilę obecną film osiągnął 349783 wyświetleń i uzyskał 8207 polubień, co świadczy o dużym zainteresowaniu społeczności i użyteczności przedstawionych treści. W kolejnym filmie David obiecuje omówić temat rozgałęziania i łączenia w Git, które są niezbędnymi umiejętnościami w codziennej pracy programistycznej.
Toggle timeline summary
-
Wprowadzenie do Gita przez Davida Mahlera.
-
Przegląd podstawowych pojęć i terminologii w Gicie.
-
Wprowadzenie do diagramów: graf commitów Gita i obszary plików.
-
Tworzenie repozytorium Gita i wykonywanie podstawowych poleceń.
-
Odniesienia, w tym książka Pro Git i Visual Git.
-
Czym jest Git i jaka jest jego rola jako systemu kontroli wersji.
-
Możliwości Gita: robienie zrzutów, przywracanie wersji.
-
Dyskusja na temat grafu commitów Gita.
-
Początkowa konfiguracja repozytorium Gita za pomocą 'git init'.
-
Konfiguracja informacji o użytkowniku w Gicie.
-
Proces tworzenia pierwszego commita w Gicie.
-
Przegląd utworzonych commitów i ich szczegółów.
-
Modyfikacja plików i dokonanie drugiego commita.
-
Tworzenie trzeciego commita poprzez usunięcie pliku.
-
Cofanie zmian w drzewie roboczym.
-
Przywracanie pliku z wcześniejszego commita.
-
Ostateczna dyskusja na temat pliku .gitignore w celu wykluczenia plików.
-
Podgląd nadchodzących filmów na temat gałęzi, scalania i zdalnych repozytoriów.
Transcription
Hello, I'm David Mahler and this is an introduction to Git. In this video, we will cover some core concepts of the version control system Git. In the video, we will gain a better understanding of central Git concepts and terminology, utilize two basic diagrams to help our understanding of what is happening when we run Git commands. The diagrams are the Git commit graph and the three conceptual areas for files in Git. We will create a Git repository and run some core Git commands. We will map all those commands to our two diagrams to help our understanding. The next two videos I put out will cover branching and merging, as well as working with remote repositories. However, I feel it is critical when learning Git to have a solid footing on some core concepts first. That will make branching and remote repositories much easier to understand. References. The primary reference for this video is the Fantastic Pro Git book by Scott Chacon, which has been made available for free under a Creative Commons license. Another site I found immensely helpful is the Visual Git reference posted by Mark Lodato. This site maps the most common Git commands to diagrams just like I'll do in this video. Let's get started now by defining Git. What is Git? Git is a type of version control system. A version control system, or VCS for short, enables you to record changes to files over time. These files could be device configs, software code documentation, anything really, however Git works especially well with text files. Some of the tasks you can perform with Git are to take snapshots of files over time. Restore earlier versions of files from snapshots you've made. Work on multiple versions of a file in parallel. For example, perhaps you are adding new features to some code. While that work is in progress, you don't want to interfere with the known working production code. Therefore, you can work on a separate version of files and keep them separate until you are ready to merge your changes into the production version. Now before we dive into a real repository, let's cover two core concepts via diagrams. The Git commit graph and the three conceptual areas of a Git project. The Git commit graph. Git tracks changes to files over time. It does this by enabling you to take snapshots of files at any time. These snapshots are called commits. We can represent these commits with a basic graph. Let's imagine we are setting up a new Git repository, more often referred to simply as a repo. We start with a standard directory on our file system. Once we have Git installed, we can turn this directory into a Git repo. Starting the repo is done with the git init command. Let's say we add two files to our directory, F1 and F2. After adding these new files, we decide to take our first snapshot, or Git commit. The commit is represented by this oval here. Now that we have our first snapshot, we can always go back to this point, to how these files looked when we took the snapshot. You might think of this a little bit like saving your place in a video game. Let's say we edit F1. Maybe we add some new lines to it. After our edits, we can capture our new changes to F1 with a second commit. So we have two commits in our commit history now. Our first commit has F1 and F2 as they were when we first created them. Our second commit has the updated version of F1. The second commit also has F2, but it hasn't changed since the first commit. Let's say we decide to delete F2 and make a third commit which includes the removal of F2. Now we've built up a history of three commits. We are currently here at our third commit. At this commit, we have F1 in its updated state, the same way it was in our second commit. Also, we no longer have F2. On our file system, we will see F1. We won't see F2 since we removed it. Since we have snapshots, we can restore earlier versions of files. For example, let's say we decide we want F2 back. We can retrieve it from the second commit here. In Git terminology, we would check out F2 from this commit. In the same vein, maybe we decide we want F1 back the way it was here at our first commit. We can retrieve or check out that original version of the file, effectively discarding the edits we made here at the second commit. Something else that is important to note. Every commit is logged by Git. Git will log who made changes and when. You can imagine how useful this can be on a large project with many contributors. That's it for a quick first look at the commit graph. As we work on our project, we change files. When we are ready, we make a commit or take a snapshot of files. A commit saves the state of the files at a particular point in time. Usually, we make a commit when a logical unit of work is done. For example, when we add a new feature, we may commit all changes related to that feature in a single commit. Now let's start talking about the three conceptual areas of a Git repo. In Git, we have three logical areas in which we work with our files. We have the working tree, the staging area, and the git history. The working tree is what we see on our file system. When we add, delete, and edit files, we do that in the working tree. The git history is equivalent to the commit graph we just saw. This history is kept in a hidden directory .git. In addition, .git directory holds an object database and metadata that makes up our repo. In fact, if we sent our .git directory to someone else, that person would have our complete Git project and its full history. They would have access to all the versions of files in any commits we made. As we are working on our project, we make changes in the working tree. We add, remove, and edit files in the working tree. Git gives us full control over which changes from our working tree we put into our next commit. For example, maybe we edited three files. However, we only want the new versions from two of those files snapshotted for our next commit. The way we get this control is through the staging area. We would add the two files we want to the staging area. When our staging area is right, we make a commit. Only the changes in the staging area are put into the next commit. The file we left out can be included in a future commit. The staging area is also known as the index. For consistency, in these Git videos, I'll stick with calling this the staging area. That's an overview of our two diagrams. Let's get started with our own Git project. These diagrams should start making more sense as we work through a real repo. Start a new Git repo. On my system, I'm using a Linux Ubuntu VM. To install Git, I ran sudo apt-get install git. For other systems, please search online for Git installation documentation. We start with the standard directory on our file system. I'll create a directory on my file system. Since I'm a network engineer, I'm going to set up a phony network automation project with YAML-based text files in it. Keep in mind, the type of project I make is not relevant for the purposes of the video. All that matters is that we have a directory and that we are adding and editing text files in that directory. Now let's move into the new directory and add a file named S1. I'll use VI, but you can use any text editor you prefer. I'll paste in some text data to represent some variables for a network switch named S1. S1 has a management IP, some VLAN names mapped to VLAN numbers, and some switch ports with assigned VLAN numbers. Let's save that data and exit. Now we have a single file S1 in our new directory netauto. We can make this directory hold a git project with the git init command. After running this command, we get back a message, Initialized Empty Git Repository. With the git init command, Git added a new hidden subdirectory, .git, into the netauto directory. Let's look at our three conceptual area diagrams to visualize what we've done. We created a directory named netauto on our file system. That directory is now our git repo's working tree. The working tree is where we add, remove, and edit files for our project. The working tree has our first file S1 in it. Next, we ran the git init command. That command created a .git subdirectory in our netauto directory. As we discussed before, this .git directory is what holds our repo. We haven't made any commits yet, so we don't have any versions of files referenced there, but we will soon. Before we get on with our first commit, we have a quick administrative task. Configuring your git username and email. Whenever we make a commit, git includes our name, email, and a timestamp with the commit. This is important for tracking when changes were made to a project and who made them. First we will set our name. git config –global user.name and then my name. Then we will set our email. git config –global user.email and then my email. git config –list shows us our name and email are set. Since we used the –global flag with the previous commands, our name and email will be used for any git repo we have on this system, so we shouldn't have to do this again. If you happen to need a different name and email for a particular repo, you can use the –local flag instead of –global. Now that we've set our name and email, let's make our first commit. Making a git commit. In our working tree, we have the new file s1. Git will call s1 untracked since it is a new file. Remember, git tracks changes to files over time. Git isn't doing any tracking for s1 just yet. However, it will once we add s1 to our staging area. Before we stage s1, let's run the git status command. The git status command tells us how things stand in our working tree and in our staging area. First we see that we are on the master branch. We will talk about branching in the next video. We are about to make our initial commit. Git status tells us we have an untracked file s1. It also tells us how to get s1 into the staging area. We stage s1 with the git add command. Git status also informs us the same git add command will make our untracked files turn into tracked files. Let's run git add now. Git add s1. Let's run git status again. And we ran git add s1 that moved s1 into the staging area. Git status expresses this by saying we have changes to be committed. In the staging area, we have our new file s1. Also note that git status no longer says that s1 is untracked like it did before. Now git is tracking s1. It's time to make our first commit. Git commit dash m quote add file s1 end quote. The git commit command creates a commit with whatever is in the staging area. For us it's just s1. Also we used the dash m option. With dash m we provide a short message describing what has been changed. We now have the first commit for our project with the single file s1. Let's take a look at the three areas diagram again to review what we've accomplished. Previously we made our netauto directory. This is our working tree. In this directory, we put the file s1. We used the git add command to put s1 into the staging area. Finally, we created our first commit with the git commit command. Let's go back to the CLI and see what git status says now. Git says we have nothing to commit, working tree clean. Nothing to commit means everything in our staging area is already committed. Working tree clean means there is nothing new in our netauto directory. Everything that's in the netauto directory we have put into a commit. At the moment, this is only the s1 file. If we look back at the output from running git commit, we also see part of a hash. Git performs a SHA1 hash of every commit that's made. It takes in the directories, files, and some metadata to create this hash. Every commit we make has a unique hash value. What we see here is the first seven hexadecimal characters of a 40-character hash. Let's check in with our commit graph. We have a single commit so far. It has a unique SHA1 hash with the first seven characters of that hash shown here. The commit has our name, email, a timestamp, and our commit message. Let's see how we get this same information at the CLI. At the CLI, the git log command tells us about our commit graph. The output shows that we have a single commit. First we see the full 40 hexadecimal character hash. Then we see the author name and email. Finally, we see the message we provided. Let's build on this by working with a second file, s2. Making our second commit. In our working tree, we can make a file s2. We can just copy s1. Let's edit s2 so that it's not the same as s1. I'll give s2 a new IP address, and I'll make some changes to what VLANs are on what switch ports. We can add VLAN 20 to port 1, and we can remove VLAN 20 from port 3. Let's also edit s1. We can add a third VLAN green with VLAN ID 30. Also, we can put port 1 in the new VLAN and save that. Let's check in with our three areas diagram. In our working tree, we have a new file, s2. Since it is new, it starts as untracked. We also modified s1. s1 is being tracked since we previously committed it. Our staging area has not changed yet. It still has s1 the way it was before our new edits. Also, s2 is not present in the staging area yet. If we run get status, this confirms the same. s1 is modified but not staged. s2 is a new untracked file. Back to our diagram. Often, we want to see the differences between tracked files in the working tree and the staging area. We can see this by using the get diff command. Here is get diff. We see how we've updated the file s1. We added the green VLAN and removed port 1 from VLAN 10 to VLAN 30. Note how get diff is not saying anything about the new file s2. That is because s2 is not tracked yet. Again, get diff shows the difference between the tracked files in the working tree and the staging area. Let's stage s1 and s2. One option is to run get add s1 s2. But instead of that, let's do get add dot. The dot means to add all new and modified files to our staging area. So that will add both s1 and s2. We could also have run get add s asterisk for the same effect using a wildcard. If we run get status, we see s1 and s2 are now both in the staging area. A quick check of our diagram shows this. Now our working tree and our staging area match. They both have the modified s1 file and the new s2 file. A moment ago, we saw how the get diff command shows the difference between tracked files in the working tree and the staging area. If we run get diff with the dash dash staged option, it will show a diff between the staging area and our most recent commit. In other words, it shows us what we are about to commit. Back at the CLI, let's run get diff dash dash staged. In the output, we see our changes to s1, and we see all the lines for the new file s2. This looks good, so let's commit these changes now. Get commit dash m, quote, add s2 and edit s1, end quote. We've made our second commit. We get a unique hash for the second commit. Let's look at our commit graph. We created our get repo with get init. We added s1 and made our first commit. We added s2 and edited s1 and made our second commit. At the shell, get log shows the same thing. Our most recent commit is at the top. Our first commit is below that. If we add the dash p option to get log, we can see what actually changed with each commit. Let's now look at a quick way to remove a file from our repo. Remove a file. Probably, the easiest way to remove a file is to use the get rm command. We can remove s2 with get rm s2. The get rm command did two things at once. It removed s2 from our working tree. It also staged this removal. Therefore, s2 is removed from the staging area as well. At the CLI, get status shows the same. We have a staged removal of s2. We can commit this removal of s2. Again, we use get commit to make a commit. This time, we will leave off the dash m option. When you leave off the dash m option, you are taken to your default file editor. For me, this is nano. From here, we can make a more detailed multi-line commit message than we would have done with the dash m option. Remove s2. Which s2 was decommissioned? Below our message is some info from get. It tells us the following. It asks us to enter a commit message like we just did. It tells us that hash marks are used for comment lines. It informs us that we can back out of this commit by not providing a message at all. Finally, it tells us what branch we are on and what we are about to commit. I'll save this file and exit. We have completed our third commit. Looking at our commit graph, we see the new third commit with s2 removed. Flipping back to the CLI, get log shows the three commits. We can see in our most recent commit that we have a multi-line commit message. We are able to do this since we left off the dash m option with the get commit command. Now that we've built up a short git history, let's see how to undo some changes. Undo a working tree change. Let's start by making a change to s1 again. We can add a bogus VLAN, bad VLAN, with ID number 0. We will save that change. Looking at our three area diagram, we see s1 has changed in the working tree, however, it hasn't been updated in the staging area yet. We didn't stage this bad config. With the get checkout command, we can replace that new s1 in the working tree with the previous version of s1 that is still in the staging area. Effectively, we would be discarding the new working tree changes. At the CLI, let's check get diff. Again, get diff shows the diff between the working tree and the staging area. So we see the new bad VLAN. Get status shows s1 is modified but not staged. In the output of get status, git tells us how to undo the modification. Get checkout dash dash s1. Now, s1 is back to how it was before we added bad VLAN. Get diff returns nothing since our working tree and our staging area match. Get status shows our modifications are no longer there, our working tree is clean. Finally, more s1 proves we have in fact discarded the bad VLAN change. Keep in mind, we can't recover the changes, we never committed bad VLAN, so it doesn't exist in the git history and it's not coming back. That's how to undo a working tree change. Let's see how to unstage a file. Undo staging of files. Let's edit s1 and stage the change. We will put port 1 in the red VLAN instead of green. We save that and exit. Get diff shows our changes. We can stage this now. Get add s1. Get diff doesn't show anything. Our working tree and staging area match, however, our last commit doesn't have the new snapshot of s1 yet, so we can use the dash dash staged option with get diff. Get diff dash dash staged. This shows the diff between the staging area and our most recent commit. Get status shows s1's newest changes are staged and ready to be committed. In our diagram, we see the modified s1 in the working tree. We added it to the staging area with get add s1. We used get diff with the staged option to see how the staged s1 is different from the latest commit. Now we can unstage s1. We do this with the get reset command. More specifically, get reset head s1. We will restore s1 from the latest commit. The term head in this context refers to the most recent commit. We will talk more about head in the next video on branching and merging. Back at the CLI. Get reset head s1. We've unstaged s1. Keep in mind, we only restored s1 in the staging area. Our working tree still has the new version of s1. Get status confirms this. We have modified s1 and it is not staged. We can also restore the working tree now with get checkout dash dash s1. Now let's look at one more undo action. Earlier we deleted the file s2. Let's recover s2 from a prior commit. Restore a file from an earlier commit. s2 isn't in our working tree anymore, and it's not in our staging area. We deleted s2 after our second commit. Let's get s2 back from this commit before it was deleted. With get log dash dash s2, we can see commits that affect the file s2. From our commit messages, we see where we added s2. It was our second commit back here. Let's get s2 back from that snapshot. Get checkout and then the commit hash dash dash s2. We're checking out s2 from the commit that starts with these five characters. ls shows we have s2 back now. Get status shows we not only put s2 back into the working tree, but we put it into the staging area as well. Let's go ahead and commit this. Get commit dash am quote restore s2. Following our three area diagram, we retrieved the file s2 from the second commit in our get history. We put it in both the working tree and the staging area with the get checkout and then the hash dash dash s2 command. Finally, we committed the restore of s2 with the standard get commit command. Okay, before we conclude this video, let's wrap up by talking about the dot get ignore file. Often in the get project, there are files you don't need get to track. Some examples could be log files, compiled code, or other non-critical artifacts. Let's put a couple of files like this in our working tree. We can make a file myapp.pyc here. Also let's create a logs directory. In the logs directory, we can put a couple of log files. Now get status shows the pyc file and the new logs directory as untracked files. We don't want get to pay attention to these files, and we can do this with the dot get ignore file. First the compiled file. We can put the whole file name here like this, myapp.pyc. Instead of that, let's use a wildcard. We know we don't want any file with the pyc extension tracked, so we can use asterisk dot pyc. Our log files are all in the logs directory, so we can ignore the entire logs directory like this. Let's save that and exit now. Running get status again, we see neither myapp.pyc or our logs files are showing up. We do have the dot get ignore file, which we need to commit to our repo like any other file. Let's do that here. Get add dot and get commit dash m quote add dot get ignore file end quote. So that's the last topic I wanted to cover in this get core concepts video. Wrap up and review. Let's wrap up here by doing a quick high-level review of what we've accomplished through one final look at our diagrams. The get commit graph shows our history of commits. Our first commit was here at the bottom when we added S1. Our last commit was a moment ago when we added the get ignore file. Every commit has our unique 40-character SHA1 hash. They also have a timestamp, our commit messages, and our name and email associated with them. Using the get log command, we can see the get history from the CLI. Here is the three conceptual areas diagram. The working tree is our net auto directory, as well as any subdirectories if they are there. This does not include the dot get subdirectory. We made our changes in the working tree. When we are ready, we stage the changes we want in our next commit. That is done with the get add command. When our staging area has the snapshots we want for a commit, we use the get commit command to make a commit. Right now, our working tree, staging area, and our latest commit all match up, so we are in a clean state. The get status command lets us know the state of files in our working tree and our staging area. We saw how to overwrite an unstaged working tree change. That was with the get checkout dash dash file name command. We saw how to unstage a snapshot with the get reset head file name command. We also saw how we can remove a file from our repo with the get rm command. Finally, we had a quick look at how we can use the get ignore file. The hidden get ignore file enables us to disregard files we don't want to be tracked in our repo. OK, that wraps up this video on get core topics. In the next video, we will talk about branching and merging, a crucial piece of working with get. After that, I will have a video on working with remote repositories. That video will also include ways to alter your commit graph, like amending commits, rebasing, and cherry picking. That's it. I hope you found this video helpful for your work. If you would like to support this page, please subscribe for more content like this. Also, as always, you can connect with me and say hello on LinkedIn. Of course, comments on the video are welcome as well. I try to answer every comment or question to the best of my knowledge. Thanks for watching.