import { addBanner, addArticle, addTitle, addHeader, addParagraph, addClassParagraph, addSubHeader } from '/scripts/article.js'; import { addInset, addInsetList, addInsetCodeListing, addInsetBulletList } from '/scripts/inset.js'; import { addImageWithCaption, addButtonGroup } from '/scripts/visuals.js'; import { addSidebar } from '/scripts/sidebar.js'; import { addSyntax } from '/scripts/code.js'; const heading = document.querySelector(".heading"); const global = document.querySelector(".global_menu"); const local = document.querySelector(".local_menu"); const sidebar = document.querySelector(".sidebar"); const main = document.querySelector(".main_content"); heading.append(addTitle("PROGRAMMING FOUNDATIONS: VERSION CONTROL WITH GIT")); heading.append(addParagraph("Christina Truong - LinkedIn Learning")); heading.append(addParagraph("Chapter 2 - Git and the Command Line")); main.append(addSubHeader("Using the Command Line")); main.append(addParagraph("I mentioned previously that you can use Git from either the command line or a GUI. In general, a GUI is easier to use and doesn't place as much of a burden on the user to learn how to use it, so you might wonder why, or even if, you should take the trouble to learn how to use the command line and there are a couple of good reasons. Firstly, using the command line gives you a better understanding of how Git works. Secondly, most (if not all) GUIs will provide you with a subset of the available functionality so the command line is the only place you can run all Git commands.")); main.append(addParagraph("There are some other benefits to using the command line that belong in the perennial command line vs GUI debate but they're not directly relevant here. As with most things, the best thing to do is to try both in order to decide which works best with you. You may decide to go with one rather than the other, but personally, I think that it is better to understand what each of them does and then use whichever is most appropriate for a given task rather than simply deciding to use just one.")); main.append(addSubHeader("Command Line Basics")); main.append(addParagraph("The commands used in the command line vary between different operating systems, but the Git commands are the same on all of them. It might be worth noting a few basic commands used in Power Shell.")); main.append(addInsetBulletList(["dir - get a directory listing", "cd - change to a different directory", "mkdir - create a directory", "rmdir - remove a directory", "cls - clears the screen"])); main.append(addParagraph("These commands will allow you to do a lot of what you need to do at the command line other than the actual Git commands, but there are lots of others of course. You can download a cheat sheet for PowerShell commands from Comparitech. There is also an A-Z of Windows CMD commands on ss64.com.")); main.append(addParagraph("As with Bash in Linux, the command prompt or PowerShell in Windows both offer auto-completion but it works a little differently in Windows. For one thing, it is not case-sensitive so if we want to cd to the Desktop directory, we can do that by typing")); main.append(addSyntax("[cd des")); main.append(addParagraph("and then enter. Assuming there is a directory called Desktop we can cd straight into and that there is no other directory that might be confused with this (that is, another directory starting des such as description, this will expand to")); main.append(addSyntax("[cd Desktop")); main.append(addParagraph("In Linux, if there is more than one possible match, the directory name won't autocomplete but you can press tab twice to see a list of possible matches. In Windows, if there is more than one possible match, it just matches with the first one that it finds.")); main.append(addParagraph("Let's start to put this into practice by creating a directory on our desktop called git-projects. When you open up a command prompt, it usually opens on the user home directory which in Windows will have a path like")); main.append(addSyntax("[C:\Users\emuba")); main.append(addParagraph("The users desktop directory is in that folder so we can just open a command prompt and enter the command")); main.append(addSyntax("[mkdir git-projects")); main.append(addParagraph("You can verify that the directory has been created with the dir command or, since you put it on the Desktop, you can see if it is there. If you want to go into that directory, you can do that with")); main.append(addSyntax("[cd git-projects")); main.append(addParagraph("Again, this makes the assumption that the directory is reachable in this way. For example, we need to navigate into the Desktop directory where we put our git-projects for the command to work as is. If we are still in our home directory, we need to add the Desktop directory so")); main.append(addSyntax("[cd Desktop\git-projects")); main.append(addParagraph("If we use the command")); main.append(addSyntax("[cd C:\Users\emuba\Desktop\git-projects")); main.append(addParagraph("since we are providing the full path to the git-projects directory, this will work regardless of what your current directory is, even the git-projects directory!")); main.append(addSubHeader("Configure Git Settings")); main.append(addParagraph("Whenever you make a commit in Git, the commit is associated with an identity and that identity is made up of a name and email address. We can set either using the git config command. For example, of I want to set the name to Philip, the command is")); main.append(addSyntax("[git config --global user.name \"Philip\"")); main.append(addParagraph("THe command to set an email address is similar")); main.append(addSyntax("[git config --global user.email \"email address\"")); main.append(addParagraph("These settings will be applied to your home directory, but because we used the global option, it doesn't matter what our current directory is. We don't need to navigate to the home directory before executing these commands, this will be set on your home directory and be applied on any respository you might create.")); main.append(addParagraph("You can set a username and email address that only applies to a specific directory and you would do that by first navigating to that directory and then issuing the git config commands shown above but omitting the global option. The user identity is then going to apply only to the repository in that directory (assuming you use a separate directory for every repository). There are lots of other coniguration options and you can get some information on those in the Pro Git book I mentioned earlier, the online chapter that covers this is 8.1 Ciustomizing Git - Git Configuration. You can also use check out the man pages in Linux with the command")); main.append(addSyntax("[man git-config")); main.append(addParagraph("Of course, you may not have easy access to a Linux system. Personally, I can run a command like that by ssh'ing into my web server which is running on a Raspberry Pi 4 or on Windows 10, you can use the Windows Subsystem for Linux (which is basically an Ubuntu shell).")); main.append(addParagraph("These two commands are enough to get you started but you could also configure other options later if you find that they are needed and you can also change your username and email address by rerunning these commands.")); main.append(addSubHeader("Setting up a Local Repository")); main.append(addParagraph("To create a local repository, the first thing you need to do is to navigate to the directory where you want to create the repository. Om Windows, the path is the prompt so you can see which directory you are in. On another system, you might want to check that, for example with the pwd command in Linux. If in doubt, you can always cd into the directory using its full path (which you should know)so that guarantees you are in the right directory.")); main.append(addParagraph("For the purpose of this exercise, we will be working in the git-projects folder we created earlier. This is intended to be a general folder containing all of our projects (or at least mutliple projects) so once we are in that directory (as a matter of interest, the full path name is C:\Users\emuba\Desktop\git-projects), so we won't create a respository here. Instead, we are going to create individual folders (note that the terms folder and directory are used in an interchangeable way here). THe next step, then, is to create a project folder. Naming the folder can be very important, especially if you are going to have a lot of projects. You want to give it a name so that when you navigate to the folder later, you don't have to guess which one holds a particular project.")); main.append(addParagraph("For the purpose of this project, the names are not hugely important but we want to use names that allow us to be clear about which folder we are talking about. We will start by creating a folder called prohect-a. At the same time, I am thinking about how I might put this into practice for my own projects so I will create an experimental folder which will allow me to start creating repositories for my own projects. I will put that in a folder on my OneDrive, in spite of the previous comments about the shortcomings when using this for VCS. Bear in mind that I only want to use this to give me better access to the folder (for example, using OneDrive, I am able to open the files for a project from my iPad or phone as well as any computer where I can log in to my OneDrive account), but this is going to be used in tandem with a VCS.")); main.append(addParagraph("The directory I will create is on my H drive and this is a directory that includes a folder sync'ed with my OneDrive. Inside the OneDrive folder, I have a folder called My Learning which in turn contains a folder called Projects so this is the folder that will contain any projects that I want to use a VCS with. Within this folder, I have two subfolders called Websites and Android which of course are intended to contain different types of projects.")); main.append(addParagraph("Going back to our git-projects folder, I have created a directory called project-a, not a very descriptive name but it is only being created for exercise purposes and I have cd'ed into that directory and now I am ready to create the local repo. THat is done with the command")); main.append(addSyntax("[git init")); main.append(addParagraph("The init command is short for initialise and it sets up the folder for version control. If you get a directory listing for project-a after running git init, you will find that it seems to be empty. Git has created a folder where it will store all of the files, but it is a hidden file so you won't see it by default but it is called .git and you can cd into it with")); main.append(addSyntax("[cd .git")); main.append(addParagraph("It is possible to get a directory listing with hidden files and folders shown by using the a option, which in Windows is preceded by a forward slash rather than a hyphen")); main.append(addSyntax("[dir /a")); main.append(addParagraph("Inside this directory, there are several files and subdirectories including a config file. We can view this file from the command prompt by using the more command")); main.append(addSyntax("[more config")); main.append(addParagraph("Apart from the hidden directory, there are no other files in our project folder at the moment simply because we haven't created any yet. We have simply set up this directory to use VCS so when we do add files to it, we will be able to use Git to track those files.")); main.append(addParagraph("I guess that you could edit the files in the hidden folder if you needed to, but you would need to be an expert with Git to be able to do that without causing problems. Assuming you're not, it is much safer to use the proper Git commands to manipulate your files and this will update the files in the .git folder as necessary, you don't have to edit them yourself.")); main.append(addSubHeader("Setting up a Remote Repository")); main.append(addParagraph("To set up a remote repository, you must first have an account with a git hosting service and for the purpose of this course, that is ButBucket so I will begin by logging into my account. When you do that, you should see something like the image below.")); main.append(addImageWithCaption("./images/bit_bucket.png", "The Bit Bucket startup page")); main.append(addParagraph("At this point, I don't have any respositories, but we can add one easily enough and there are several ways to do that. If I select Respositories from the Menu in the sidebar, this will list any repositories attached to my account and from there, I can click the Create respository button.")); main.append(addParagraph("Alternatively, I can click on the + sign in the sidebar (which actually allows me to create a Repository, Workspace, Project or Snippet or import a Respository. This brings up a dialog box which is different to the one shown in the video. The box that I see is shown in the image below.")); main.append(addImageWithCaption("./images/bit_bucket2.png", "The box that appears when you create a respository in BitBucket")); main.append(addParagraph("In the image shown, I have already typed in project-b as the project name and main as the name of the default branch. The significant difference between this and what I can see in the version on the course video allows the user to select a VCS (Git or Mercurial). I don't see that option so I would assume that Git is being selected automatically. I also have a Workspace shown and that isn't present in the version on the course video.")); main.append(addParagraph("I will give the respository the name project-b and will accept the default option for the ReadMe file. Aside from that, at this stage, we are just going to accept any default options (although, that really applies more in the course video because the only other option for me is the project n\me which wasn't required in the course video. I have also selected project-b for the project name and clicked on the Create repository button and that creates the repository.")); main.append(addParagraph("When done, we them see the project page for this new project as shown below.")); main.append(addImageWithCaption("./images/bit_bucket3.png", "The BitBucket home page for project-b")); main.append(addParagraph("From the home-page, we can edit or add files and it can ber useful to be able to edit our files in the browser, but in most cases, you will want to edit the files locally so to do that, you will need to create a local copy. We do that by cloning the repo. This will give us a duplicate of the project on the local machine, but it will also create a link between the remote repo and the copy we store locally (the clone) which will allow us to sync files between the two.")); main.append(addParagraph("As you can see in the previous screenshot, there is a clone button in the top right corner so we are going to click that. There are two options when cloning, HTTPS or SSH. The choice depends on how you authenticate your BitBucket account and we didn't create an SSH key so we will have to take the HTTPS option. Once selected, BitBucket provides you with the command you need to perform the cloning operation and it will normally look something like this.")); main.append(addSyntax("[git clone https://Thorloki@bitbucket.org/thorloki/project-b.git")); main.append(addParagraph("Git clone is the Git command and the VCS may not always provide this so if you only get the URL, you will need to add this manually. You can't put a repository inside another repository so back at the command prompt, we will add a folder inside the git-projects folder to hold the clone of the remote repository. We will call this folder project-b and once created, we will navigate to it and enter the git clone command along with the URL.")); main.append(addParagraph("You may be asked to enter your BitBucket password which I wasn't. I was, however, asked to input an App password which Christina wasn't - it does give you the URL for that which is https://bitbucket.org/account/settings/app-passwords/. To generate the code, I had to provide an app name and I've just used the project name. I also had to select the appropriate permissions and I have just selected everything for that. When the password appears, there is a warning letting you know that once you close the dialog box that gives you the password, you won't be able to access it again so it is a good idea to record it and I have put a copy of it alongside my BitBucket password. With that entered, the git clone command went ahead and cloned the repository.")); main.append(addParagraph("Actually, I made a mistake by creating the project-b folder and navigating to it before executing git clone because when I was done, I had a folder called project-b inside the project-b folder I had created so obviously, the command creates the folder for you. I deleted the respository and the folder I had created for it and ran the git clone command again, this time inside the git-projects folder. The output I got from this command is copied below.")); main.append(addInsetCodeListing(["C:\Users\emuba\Desktop\git-projects>git clone https://Thorloki@bitbucket.org/thorloki/project-b.git", "Cloning into 'project-b'...", "git: 'credential-manager' is not a git command. See 'git --help'.", "", "The most similar command is", " credential-manager-core", "Password for 'https://Thorloki@bitbucket.org':", "git: 'credential-manager' is not a git command. See 'git --help'.", "", "The most similar command is", " credential-manager-core", "Unpacking objects: 100% (4/4), 1.71 KiB | 62.00 KiB/s, done."])); main.append(addParagraph("I am a bit concerned about the message displayed which may be an error or just a warning but the task seems to have been successfully completed so I won't worry about it for now. I can now cd into the project-b directory and see the readme file that was created with the project and I cna view it using the more command. Just as a side note, the Windows command prompt does recognise the more command but not less. It also doesn't recognise the edit command. Admittedly, it is many years since I have used a command prompt for anything other than a single command so I had to look this up. The edit command is one I used to use quite a lot, but it seems that it only works with 32 bit versions of Windows so it is not available on my PC (or, I guess, the majority of modern PCs).")); main.append(addParagraph("There is an interesting tutorial to help you understand the difference between HTTPS and SSH authentication on the atlassian.com website, in an article called What is an SSH KEY?. Having had a quick look through it, one interesting point is that you can create an SSH key using the git bash shell which seems to operate more like a Linux shell. From a brief look at it, it seems to respond to both Linux style commands such as ll or pwd, but also MS-DOS style commands such as dir so it may be a better option for working with Git than the command prompt. Especially if, like me, you are more accustomed to working with a shell in Linux. It also made the point that you can use the Ubuntu shell in Windows 10 which again may be a better option since it avoids the need to get acquainted with MS-DOS commands again and either of these would be a more familiar kind of command line option, for me at least!")); main.append(addParagraph("As a matter of interest, the Ubuntu shell in Windows mounts the C drive in /mnt/c/ and has similar mount points for other Windows drives so you can navigate to the git-projects folder with the following cd command")); main.append(addSyntax("[cd /mnt/c/Users/emuba/Desktop/git-projects")); main.append(addParagraph("Another quick point, when I was checking this, I realised that a Bash shell in Linux does actually recognise dir as a command which I hadn't been aware so presumably that's why the Git Bash shell recognises it!")); main.append(addSubHeader("Adding Changes with Git add and commit")); main.append(addParagraph("Once you have set up the repository, most of the work you will be doing with it will involving adding files and making commits. To demonstrate this, we will edit the read me file. You can do that at the command line, but most of the time when you are editing source code or whatever is in your project, you will be using some tool such as Visual Studio or Dreweamweaver. You may well be adding and committing files using that tool, but for now, we will assume that changes are made in an IDE or text editor and Git commands are issued via the command line.")); main.append(addParagraph("I have opened the file in Atom and for reference, I have created a page with the comtents of the README.md file. This is a markdown file which is something that is new to me so worth mentioning here. It's a little like a markup file but it is used to style plaintext documents and you can get more info on it at markdownguide.org.")); main.append(addParagraph("It is pretty straightforward and uses things like an asterisk at the beginning and end of some text to italicise it, two asterisks for bold and a # symbol to designate a heading (the level is denoted by the number of # symbols so # is equivalent to h1 in HTML, ## is equivalent to h2 and so on. There is no real requirement for a read me file to be in this format but because it looks better than plaintext, it is quite common in respositories.")); main.append(addParagraph("In Atom, I will delete all of the template text from the file and add the following text")); main.append(addInsetCodeListing(["## Sample Git Project", "", "This repo has been created for test purposes only"])); main.append(addParagraph("The actual text doesn't matter, the only important thing is that we have made a change. Next, I'm going to open a command prompt and navigate to the project directory (for project-b) and run the following command")); main.append(addSyntax("[git status")); main.append(addParagraph("This gives me the following output")); main.append(addInsetCodeListing(["C:\Users\emuba\Desktop\git-projects\project-b>git status", "On branch main", "Your branch is up to date with 'origin/main'.", "", "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: README.md", "", "no changes added to commit (use \"git add\" and/or \"git commit -a\")"])); main.append(addParagraph("There is quite a bit of information here. We can see that we are working on the main branch and that there is one file that has been modified. Going back to the three areas we discussed earlier, this file (README.d) is in the Working Directory.")); main.append(addParagraph("We can also see that the branch is up to date with the origin/main which is just telling us that the version history in the loca repo is the same as the version history in the remote repo. This may come as a surprise since we have made a change and we can see that the file is listed as modified. However, this is listed under Changes not stages for commit which is just a way of saying that there is a change to the file in the Working Directory, but that change has not been moved to the Staging Area so the change has not yet been added to our local repo and that's why the local and remote repos are still identical.")); main.append(addParagraph("Our next step will rectify that with the git add command. There are several arguments we can use with git add, including")); main.append(addInsetBulletList(["git add -A This stages all changes including new modified or deleted files.", "git add . This stages new or modified files, but not deleted files.", "git add -u This stages modified or deleted files, but not new files.", "git add <file> This stages the specified file only."])); main.append(addParagraph("Bearing in mind the fact that we only have one modified file (no new or deleted files) any of these option would work for us so we may as well use the simplest.")); main.append(addSyntax("[git add .")); main.append(addParagraph("This doesn't tend to give you any output although I did see a warning:")); main.append(addInsetCodeListing(["warning: LF will be replaced by CRLF in README.md.", "The file will have its original line endings in your working directory"])); main.append(addParagraph("This is just because of the line endings in the file not being compatible with md (I guess) but I am not too concerned about it. Without that warning, there would be no output. However, we can run git status again (we can run it at any time to check whether we have unstaged or umcommited files). This time, I get the output shown below.")); main.append(addInsetCodeListing(["C:\Users\emuba\Desktop\git-projects\project-b>git status", "On branch main", "Your branch is up to date with 'origin/main'.", "", "Changes to be committed:", " (use \"git restore --staged <file>...\" to unstage)", " modified: README.md"])); main.append(addParagraph("The local and remote repos are still the same, but this time, the modified file is listed inder changes to commit rather than changes not staged for commit.")); main.append(addParagraph("We are now ready to commit the changes and we do that with a git command. Whenever we make a commit, we need to also add a message which is just a note to explain what the purpose of the commit is so this would often just be a note of the file or files being updated. Essentially, when you review the version history, the message added to each commit should give you some notion of why each version exists. In this example, we are updating the read me file so the full command will be")); main.append(addSyntax("[git commit -m \"Updating readme\"")); main.append(addParagraph("The output we get from this is")); main.append(addInsetCodeListing(["C:\Users\emuba\Desktop\git-projects\project-b>git commit -m \"Updating readme\"", "[main a08e4c6] Updating readme", " 1 file changed, 3 insertions(+), 45 deletions(-)", " rewrite README.md (99%)"])); main.append(addParagraph("We can see here that 1 file has been changed and this included 3 insertions (the three lines that we added) and 45 deletions (the lines deleted from the original file). If we run git status again, the output we get is")); main.append(addInsetCodeListing(["C:\Users\emuba\Desktop\git-projects\project-b>git status", "On branch main", "Your branch is ahead of 'origin/main' by 1 commit.", " (use \"git push\" to publish your local commits)", "", " nothing to commit, working tree clean"])); main.append(addParagraph("We can see that there are no files in the staging area and nothing waiting to be committed. However, we do see that our branch is one step ahead of the 'origin/main'. This is really just letting us know that we have committed the change to the local repo but this hasn't been updated on the remote repo. It is important to remember that when we perform a git commit like this, we are still working with the local repo. We need to do a bit more to sync the local repo with the remote repo. There are two commands that we use to do that, depending on whether we want to communicate changes in the local repo to the remote repo (as, for instance, when out branch is ahead of the remote repo, which it is at this point) or where there are changes in the remote repo that we don't yet have in our local repo.")); main.append(addParagraph("The two commands to do that are git push and git pull and we will look at these next.")); main.append(addSubHeader("Keep Repositories Up ot Date with Git pull and push")); main.append(addParagraph("We want to sync our local repo with the remote repo and as I mentioned earlier (and this was also mentioned in the last status report), we are going to use a git push. With a git push command, we need to proivde two pieces of information, the remote name and the branch name. The last time we ran git status where we saw the message that told us that the local branch was ahead of origin/main")); main.append(addSyntax("[Your branch is ahead of 'origin/main' by 1 commit.")); main.append(addParagraph("we mentioned earlier that main was the name of the branch. Origin is the name of the repo. So the full command will be")); main.append(addSyntax("[git push origin main")); main.append(addParagraph("When the command is executed, we get the folllowing output")); main.append(addInsetCodeListing(["C:\Users\emuba\Desktop\git-projects\project-b>git push origin main", "git: 'credential-manager' is not a git command. See 'git --help'.", "", "The most similar command is", " credential-manager-core", "Password for 'https://Thorloki@bitbucket.org':", "git: 'credential-manager' is not a git command. See 'git --help'.", "", "The most similar command is", " credential-manager-core", "Enumerating objects: 5, done.", "Counting objects: 100% (5/5), done.", "Delta compression using up to 8 threads", "Compressing objects: 100% (3/3), done.", "Writing objects: 100% (3/3), 343 bytes | 343.00 KiB/s, done.", "Total 3 (delta 0), reused 0 (delta 0), pack-reused 0", "To https://bitbucket.org/thorloki/project-b.git", " 3111a77..a08e4c6 main -> main"])); main.append(addParagraph("We only had one file to commit but the git push will upload all the commits which have been made since the last git push command was executed. In BitBucket, we can see the read me file and that it contains three lines, see the image below.")); main.append(addImageWithCaption("./images/bit_bucket4.png", "The amended read me file viewed in BitBucket")); main.append(addParagraph("Above the read me file, we can see a list of commits which shows both the initial commit (when the repo was created) and the commit we have just made. The ,essage associated with each commit is also shown as we as the time of the commit. Notice that the commit shows that it was made an hour ago. Each commit has an associated time stamp which shows when the commit was made. Note - this is the time when the commit was made (in other words when the git commit command was executed. It is not the time when the commits were pushed to the remote repo.")); main.append(addParagraph("We can also view a list of commits if we select Commits in the panel on the left hand side. This is similar to the view shown in the previous image but we also see an author name which I had added earlier to git with the git config command. Given that I have committed both the initial and subsequent commits myself, it's not really a surprise that my name is associated with both (see the image below).")); main.append(addImageWithCaption("./images/bit_bucket5.png", "The list of commits in BitBucket")); main.append(addParagraph("However, these are not really the same name so you shouldn't be surprised, for example, if you create a respository yourself and see that there is a difference. For example, you may have a different username associated with the local and remote repos.")); main.append(addParagraph("So that's that for creating our first commit. It may sometimes seem as though you only ever push files to the remote repository, but there are a number of reasons why you might want to get the files from the remote repo to your local repo and these include")); main.append(addInsetBulletList(["where someone else created the remote repo", "where someone else has access to the remote repo and has added commits that you want to bring over to your local repo", "where your local repo has become damaged due to a damaged hard drive, accidentally erased files and so on", "where you want to create a local repo on another computer, for example if you usually work on a PC and you want to work on a laptop"])); main.append(addParagraph("In this course, we won't use git pull very much, but in terms of usage, it's the same as git push so it uses the same two arguments.")); main.append(addParagraph("Editing a file in BitBucket is certainly possible but it isn't really very intuitive. We need to click on source in the top left, double click the file name and then click on the Edit link in the bar above the file (see the image below). Note that when you finish editing, you don't save the file, you commit it so obviously there is no staging area here so let's check what happens when we do that.")); main.append(addImageWithCaption("./images/bit_bucket6.png", "Editing a file in BitBucket")); main.append(addParagraph("I have clicked edit and added a line and clicked commit. A dialog box pops with a commit message which gives you a default you can just accept, but I have added a bit more text to this to make it a bit more descriptive (see the image below).")); main.append(addImageWithCaption("./images/bit_bucket7.png", "Committing a file in BitBucket")); main.append(addParagraph("Note that you can create a pull request at this stage but I'm not really sure exactly what that does so I will ignore it, for now at least.")); main.append(addParagraph("Back at the command prompt, I am still in the project-b directory so I can run the pull command from there, I have executed the git pull command like this")); main.append(addSyntax("[git pull origin main")); main.append(addParagraph("As an aside, I did run a git status command first but it didn't tell me anything wjich is not really surprising since the commit is on the remote repo, so the local repo won't be aware of it until I run the git pull command (as far as I know, I guess there may be a command you can run to check the status of the remote repo without executing git pull but again, that's probably a bit too advanced for this course.")); main.append(addParagraph("The output from running the git pull command is")); main.append(addInsetCodeListing(["C:\Users\emuba\Desktop\git-projects\project-b>git pull origin main", "git: 'credential-manager' is not a git command. See 'git --help'.", "", "The most similar command is", " credential-manager-core", "Password for 'https://Thorloki@bitbucket.org':", "git: 'credential-manager' is not a git command. See 'git --help'.", "", "The most similar command is", " credential-manager-core", "remote: Enumerating objects: 5, done.", "remote: Counting objects: 100% (5/5), done.", "remote: Compressing objects: 100% (3/3), done.", "remote: Total 3 (delta 0), reused 0 (delta 0), pack-reused 0", "Unpacking objects: 100% (3/3), 435 bytes | 16.00 KiB/s, done.", "From https://bitbucket.org/thorloki/project-b", " * branch main -> FETCH_HEAD", " a08e4c6..7ac6543 main -> origin/main", "Updating a08e4c6..7ac6543", "Fast-forward", " README.md | 2 ++", " 1 file changed, 2 insertions(+)"])); main.append(addParagraph("Again, this is fairly explanatory and provides a brief summary of the changes. It tells me that the README.md file has changed, that 1 file was changed and that two insertions were made. In case this wasn't obvious when we saw the number of insertions in the original file when it was committed, I added one line of text, but of course, there was also a blank line added so this is two new lines, therefore two insertions.")); main.append(addParagraph("That's pretty much it as far as pull commands except that it is possibly worth mentioning that you can commit any changes in a project, it doesn't have to be a kind of a milestone. The important thing is to remember to add clear commit messages and perhaps to bear in mind that if you do make a small change and you don't think it is worth committing it to the remote repo, there is always the danger that you will forget that the change has been made. If you only add commits when there have been significant changes to the project, you may well find that the commit messages are very broad and don't convey much in terms of the detail of those changes. As a result, I guess that the important thing is to make a change when you want to not only commit a change to the remote repo, but also when you want, or need, to have a clear record of that change being made. The key is to use git, whether with BitBucket or some other hosting service and things like knowing what to commit and when will become clearer as you become more experienced.")); main.append(addSubHeader("Deleting a Repository or Branch")); main.append(addParagraph("Deleting a local repository is pretty straightforward. It can be done from the command line, but you can do it much more easily. Essentially, the goal is to delete the entire folder and you can do that in several ways. For example, you could open the project folder in File Explorer and just delete it or delete it through the command line with a standard delete command. In other words, you just need to delete the files and you have deleted the local repo.")); main.append(addParagraph("It might be worth mentioning again, however, that you can delete the folder (thereby deleting the local repo) but you can still use a git pull command to recreate it if you need to. You may also be able to restore it in Windows by simply opening up the recycle bin and restoring it from there.")); main.append(addParagraph("To delete the remote repo, you would have to log in to the hosting service and do it from there. In order to try this out, I have created a repository called Delete Test and called up a list of all the repositories I now have as shown in this image.")); main.append(addImageWithCaption("./images/bit_bucket8.png", "List of repositories in BitBucket")); main.append(addParagraph("This list is accessed simply by clicking Repositories in the menu on the keft hand side. We want to access the repository, Delete Test in this case to bring up the repo's home page shown below.")); main.append(addImageWithCaption("./images/bit_bucket9.png", "The home page for our Delete Test Repository")); main.append(addParagraph("In the menu to the left, there is a Repository settings options and clicking on this beings up this screen.")); main.append(addImageWithCaption("./images/bit_bucket10.png", "The home page for our Delete Test Repository")); main.append(addParagraph("Next, we want to click the drop down arrow in the Manage Repository button in the top right and select Delete repository and you will see a dialog box (shown below) with a delete button so it is essentially asking you to confirm that you want to delete the repo.")); main.append(addImageWithCaption("./images/bit_bucket11.png", "The Delete repository confirmation dialog")); main.append(addParagraph("Note that it gives you a potentially useful option to confirm the new URL for this depository in case any other user still needs to access it. For example, if other users have access to it and they don't know that it has been moved, if they try to access it after it has been deleted, they will see the URL you put here.")); main.append(addParagraph("It's pretty clear from this that deleting the remote repo is a more convoluted process and it took me a few minutes of searching through various options to work out how to do it, but I would assume that whatver hosting service you use, deleting the repo comes down to finding that delete option and clicking it.")); main.append(addSubHeader("Challenge: Putting it All Together")); main.append(addParagraph("For the purpose of this challenge, the course uses the website template included with the exercise files, but I will try to create a real repository with this website. The steps that should be completed for the challenge are as follows:")); main.append(addInsetBulletList(["Step 1 - Create a remote repo in BitBucket", "Step 2 - Clone the repo to make a local copy", "Step 3 - Add some file to the local repo amd commit them, also to the local repo", "Step 4 - Update the read me file to provide a description of the project", "Step 5 - push both commits to the remote repo"])); main.append(addParagraph("This seems reasonably straightforward. In BitBucket, I have created a project called MyLearningWebsite and given the repo a name of learning_website.")); main.append(addParagraph("I have opened up a command prompt and cloned the repo with the git clone command obtained from BitBucket by clicking Clone from the project homepage and copying the git clone command using the HTTPS option. The command and its output are shown below.")); main.append(addInsetCodeListing(["H:\Downloads>git clone https://Thorloki@bitbucket.org/thorloki/learning_website.git", " Cloning into 'learning_website'...", " git: 'credential-manager' is not a git command. See 'git --help'.", "", " The most similar command is", " credential-manager-core", " Password for 'https://Thorloki@bitbucket.org':", " git: 'credential-manager' is not a git command. See 'git --help'.", "", " The most similar command is", " credential-manager-core", " Unpacking objects: 100% (4/4), 1.71 KiB | 3.00 KiB/s, done."])); main.append(addParagraph("One point I had forgotten is that the clone command creates the directory for you so I had initially navigated to the folder with my website in it before running git clone. I don't want to rename my existing folder and it's probably good practice to do it again and do it right in order to reinforce the learning experience so I will go back to BitBucket and rename the respository website (via the Respository settings). I will also take the opportunity to put the folder in a new location so I will open up the Documents folder from the command line and run the command again (so I will then have the local repo in a folder called Website which is in my Documents folder). For me, my documents folder is on an external drive, my H drive so inside that folder, I will run the git clone command again.")); main.append(addParagraph("The next step will involve moving all of these files over to the staging are so we are going to use a git add command with the appropriate option, Either -A or . would work so I will go with -A giving the command as")); main.append(addSyntax("[git add -A")); main.append(addParagraph("Because of the number of files in the project, this takes quite a while and the outout is really nothing more than a list of files, each with a warning about the line endings, a sample of this is")); main.append(addInsetList(["warning: LF will be replaced by CRLF in webdevelopment/cssessentialtraining/project_files/Exercises/Ch8/08_08/final/css-portfolio/index.html.", "The file will have its original line endings in your working directory", "warning: LF will be replaced by CRLF in webdevelopment/cssessentialtraining/project_files/README.md.", "The file will have its original line endings in your working directory", "warning: LF will be replaced by CRLF in webdevelopment/cssessentialtraining/project_files/css-portfolio/css/styles.css.", "The file will have its original line endings in your working directory", "warning: LF will be replaced by CRLF in webdevelopment/cssessentialtraining/project_files/css-portfolio/index.html.", "The file will have its original line endings in your working directory"])); main.append(addParagraph("Before I move on to the final step, I've just run a git status command in the website folder to make sure everything looks okat and it does. I have a long list of new files and just one modified file which is the readme file.")); main.append(addParagraph("The final step is to push the changes to the remote repo and I have checked the branch and repo names shown by the previous git status command so my push command is")); main.append(addSyntax("[git push origin master")); main.append(addParagraph("Actually, this didn't work because I have added the files (which moves them to the staging area, but I forgot to commit them with the git commit command so I have done that now")); main.append(addSyntax("[goit commit -m \"Adding all of my existing website files to the remote repo\"")); main.append(addParagraph("Now I've run the git push command again and that seems to have worked. The output from this command is")); main.append(addInsetCodeListing(["H:\Documents\website>git push origin master", "git: 'credential-manager' is not a git command. See 'git --help'.", "", "The most similar command is", " credential-manager-core", "Password for 'https://Thorloki@bitbucket.org':", "git: 'credential-manager' is not a git command. See 'git --help'.", "", "The most similar command is", " credential-manager-core", "Enumerating objects: 762, done.", "Counting objects: 100% (762/762), done.", "Delta compression using up to 8 threads", "Compressing objects: 100% (708/708), done.", "Writing objects: 100% (760/760), 26.22 MiB | 652.00 KiB/s, done.", "Total 760 (delta 193), reused 0 (delta 0), pack-reused 0", "remote: Resolving deltas: 100% (193/193), done.", "To https://bitbucket.org/thorloki/website.git", " 6a13d48..ca64252 master -> master"])); main.append(addParagraph("I can go back to BitBucket and see the commits as shown in the following image.")); main.append(addImageWithCaption("./images/bit_bucket12.png", "The list of commits for the project, MyLearningWebsite")); main.append(addParagraph("I can also click on Source in the menu to the left to see that the website files have been added to the remote repo as shown below.")); main.append(addImageWithCaption("./images/bit_bucket13.png", "The source 'code' for the project, MyLearningWebsite")); addSidebar("programming");