An Intro to Pushing Code to GitHub and Creating Pull Requests

In this short lesson, we'll take a bit of a tangent and talk about something we haven't talked about it in the course - creating Pull Requests for features

Project Source Code

Get the project source code below, and follow along with the lesson material.

Download Project Source Code

To set up the project on your local machine, please follow the directions provided in the README.md file. If you run into any issues with running the project source code, then feel free to reach out to the author in the course's Discord channel.

This lesson preview is part of the TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two course and can be unlocked immediately with a \newline Pro subscription or a single-time purchase. Already have access to this course? Log in here.

This video is available to students only
Unlock This Course

Get unlimited access to TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two, plus 70+ \newline books, guides and courses with the \newline Pro subscription.

Thumbnail for the \newline course TinyHouse: A Fullstack React Masterclass with TypeScript and GraphQL - Part Two

In the last couple of lessons, we wrote tests for both the login component and the home component. The home component was a component similar to a lot of components in our client in which its responsibility was to just simply query for information and have it displayed and some other minor functionality. So I just having the search inputs. The login component was a little different because the login component was primarily focused on having user action be conducted. So a user was able to authenticate with Google and they'll be navigated away. And when the user is navigated back, we fire the login mutation with the presence of a successful authentication code in the URL. And in the last lesson, I quickly summarized the fact that as you move from components to components, a lot of the thinking processes that we just did is going to be very similar. Right? We're simply going to think about how we're going to sort of structure our tests in such a way that makes sense. We're going to think about what we're going to try to test, we will use the libraries we've been using. And in my opinion, the only slightly trickier different parts you'll notice is how you can find the nodes you're looking for in the components you're working with and trigger the actions or events that you want. Other than that, the expectation is very similar. And you'll often find yourself going to the API documentation for React, testing, library, or just to get some hints on what you're trying to do. Lesson, we're going to talk about something a little different, but I thought it would be pretty helpful for people who might be new to this, who aren't familiar with the idea of pushing code. So you might have noticed that throughout the course, part one or part two, we didn't really talk about Git. We didn't talk about version management. We didn't mention how you push code. And as we moved from lesson to lesson or module to module, we just kept working and working. However, traditionally, if you're working in an actual app, that's slightly large. And if you're most likely working with other people or other developers, you would need to use some sort of version control system. You might be familiar with how Git or version control works. So I'm not going to spend too much time here. But here, for example, assume the entire repo here that I've been working with has been pushed into some repository that I've just set up right now called dummy test repo. Right? It has all the central files. I just pushed it all a few minutes ago. What I'm trying to convey in this particular lesson is how within real production settings or within real production apps, when you're working with a team of people, how I usually approach actually having code be pushed onto master. So in this instance, I only have a single branch in this repository, right? Master it. When a deployment pipeline is usually set up, oftentimes a deployment pipeline is set up for a certain branch. So with this continuous integration model that a lot of production applications do, the fact that certain people push code or merge code onto a certain branch, let's just say master, that particular code is automatically deployed. Right? So think of it this way. Assume that if I just simply push something right up and I changed text somewhere in one of my components and I automatically merged it to master within a few minutes is deployed to everyone or all the users that are using the app. Depending on how large an application you're working on, pushing code to master is a pretty, I guess, serious thing. Let's assume you're working on an app that has millions of users. You can't just directly push to branches like this, especially if these branches are the branches that automatically deploy code. And as often for this reason, branches like this are usually protected where people just can't push directly to the branch that serves as production. Now a quick tangential note. I'm not sure when you'll be watching this lesson, but at the time of recording, there's been some discussion around the tech community about bad terminology, such as master or, you know, whitelist or blacklist. I'm just referencing master here, which is the original term often used for the main branch that people usually would use for production settings. This branch can be named anything, right? It could be production. It could be main. Let's just assume in this context right now, this particular branch is protected and we're trying to get new code into this particular branch. So how would we go about doing this? If you go back to our code base, assume that everything in this particular repository exists, except for the login functionality. Let's assume right now I just finished working on creating this entire login component. I just finished working on creating the test for this component. I've, you know, introduced whatever assets are necessary. And I'm now interested in pushing all this code and having it in the main master branch of my repository. If I head to my terminal, I won't spend too much time talking about the git commands, but let's assume I can see git status to see the changes that have been currently untracked. I can see that locally I've made some changes in this login folder that can be added and move the long. I check on my branches right now. I am on the master branch. So I'm not going to directly push this code onto master. So what people would often tend to find themselves doing is they'll check out to a new branch, get checkout minus brie, and they'll name this branch along the lines of the work that they're conducting. So in this instance, I can say something like login functionality. So now I'm in a new branch called login functionality. With that being said, I can now add these changes. So I'm saying, you know what? I actually want to commit these changes up. So add them with these changes now added. I have the login components file, I have the test file and whatever assets I'm using, I'll make a useful commit message specifying the change I'm doing. So I'll say introducing login functionality. Now, there's a lot of discussion in the community about good commit messaging and appropriate ways to do so. I'm not going to go down that rabbit hole. Let's just say we're just going to use a brief message like introducing login functionality. Once that change has been introduced, I can now push these changes up to the remote version of the local branch I'm using. So I'll say, get push origin, login functionality. Once this has been pushed, I can now head back to my repository and it would automatically pick up the fact that I've actually created a new branch. So not only do I have master branch now, I have a new branch in my remote setting called login functionality. And it gives me the prompt to say, do I want to compare and create a pull request? And that's pretty much what I would want to do. If I want to merge a new functionality onto a protected branch, I would create a pull request and have people review this particular request. By opening this pull request, I now see the changes that I've made. I can see that, okay, this is the entire login component. It has all the functionality that I'm looking for. And these are the tests associated for this component. When it comes to PR descriptions, depends on the setting that you're working in . I like to really make my descriptions as detailed as possible. So I'm not going to go through writing an entire description now, but some of the stuff that I'll look to compile first and foremost is what does this PR do, right? So a detailed description on what is this PR doing? What is it adding? What is it changing? What is it modifying? Why is it doing so? Etc, etc. Second, I'd also add a particular section. If I have any comments or questions or just open discussions, I want people to keep in mind. So, you know, just open questions, discussions, notes. So if there's anything in this PR that I've potentially thinking about or concerned or wondering is there a better way of doing so, I'll do it here. You know, I'll provide information for the reviewers to take into account. And lastly, another big section that I'll always try to fill is specifically if you're working on a client application, you know, we're working on pieces of work that 's going to be visual to the user, right? The user is going to be able to interact with the work that we do. So ideally, if the reviewers have time, I always try to encourage folks or people around me would encourage me as well, likewise, to test these changes. So ways to test these changes. And I'll literally list step by step what needs to be done. So I'll be like, check out this branch. Once this branch is checked out, go to /loggin because that's the new route that this particular PR is going to work with. Click the authentication button. Apply that you're able to sign in to Google servers. And then finally, when redirected back, perhaps verify your logged in and taken to the user page, right? And in cases like this where I want to provide testing information just for people to quickly go through the work, I would often provide images. Images have the power of more than 1,000 words, right? So visually show what this login page looks like. Show how you're being navigated away. Show how you're often taken to the user page, right? And only when I have all this set up, I'll then add a reviewer. Perhaps I'll say, you know, there's no one in this PR, sorry, in this repository because it's just me. But whoever is in this particular repo, I'll add reviewers to review my work. And then I'll just create my pull request, right? Once my pull request is created, I have all this functionality set up. I'll wait for people to actually review my work. And the one point that I want to make here that's relevant to, I guess, the testing side of things is whenever code is often pushed in a secure setting or in a production setting, it should be expected from the person that tests are pushed as well, right? Now, there are some times or unique cases when you're just working on a personal project, or you're working in a time intensive setting where you need to get something out very quickly, then in these cases, I've been in situations where I'll just quickly push something in which tests aren't considered. However, when all other conditions are met and everything is in the perfect setting, an ideally code should always be pushed with tests. So if I'm a reviewer right now, this is how other pros looking through this PR. First and foremost, I'll go through the description and I'll be like, okay, what does this PR do? What is this person trying to comment on? What issues are they closing? How do you actually test these changes? Before I will go to test these changes, I'll see the changes that have been made. So I'll notice that, okay, this person created a new component. This component is probably being used in the root level. They're using all of this stuff here. I'll go through a detail of the process, see if they're doing anything that could be approved upon, see the calling parent function, blah, blah, blah, etc, etc, etc . And then shortly after this, I'll automatically go to the tests. Why? Because the tests, if done well, would oftentimes describe the work being done, right? So right here, I can see, okay, this person's created a test for the login component. This guy's creating, or this person's creating a test around the authentication URL query. What is this query supposed to do? It's supposed to redirect the user when the query is successful. Okay, how does this person do the test? They mocked the request to be successful. So right here, I can see, okay, this is the kind of graph kill response that the client is expecting. It's going to return a particular string, which is the authentication URL. And what happens at the very end is the user has to click a certain button. This button is just a button that exists in the component template. When this button is successful, what is the expectation? We expect the window location to have been called with this. So we expect the user to have literally been redirected to the URL that's specified from the response. So what I'm trying to sort of convey here, and hopefully I'm doing a good job of it, is when tests are done well, they oftentimes describe the work being done. And it's helpful for the person doing the tests. It's helpful for the people reviewing the work as well, right? And right away, I can go on and see what else happens. So what actually happens when the query is unsuccessful? This person says it does not redirect the user. So what actually happens is, oh, it seems like an error message is so, queried by text or a word able to log you in. And this continues on and on and on. So the key aspect that I'm trying to convey here is tests are incredibly important for many reasons, right? They allow you to architect your code better. They allow you to understand what you're doing better. They allow other people to look through your test and say, okay, this is what the person's trying to do. When this code eventually gets merged in, now if anybody else starts to introduce work or push work that break one of your tests, the continuous integration pipeline oftentimes will be running your tests before they get pushed to production. So they'll be able to understand that something got broken. And lastly, this assume I'm now playing the role the person who had this PR created assume I got the reviews I needed, assume I added any of the address, any of the comments that would be made. And quick tangential notes. As I mentioned, if continuous integration is set up with whatever tooling that is used, sometimes this CI pipeline will run the tests before you can merge your request . So oftentimes in a production setting, you're not encouraged to merge until the integration pipeline has run through all the tests in the app to be like, everything's running perfectly, go ahead and merge, right? And this is helpful because now it gives me the security and it gives me the, I guess, yeah, the security or the fact that I know that if this is done well and all the tests pass, most likely my PR is not going to break anything. And going back to what I was just saying, assuming everything is good and the pipeline is done properly and I have the reviewers that I'm looking for. The only done would I then merge my pull request. I'll specify that the question should be merged. I want to change any description I would. And finally, I'll just delete my branch. And in this instance, I now have the work that I've just done pushed on to the main production or in other words, master branch. And yeah, that's pretty much what I wanted to mention in this lesson. It's not really directly related to any of the testing work we were doing directly, but I thought it would be helpful for people who are just interested to see maybe some of the steps that folks would usually take maybe within the actual production app setting when it comes to pushing or introducing new code. [BLANK_AUDIO]