Git and GitHub Basics
These are technical notes I compiled while studying using Trailhead, Salesforce's free self-learning portal.
Learn Why Version Control Is Important for Team-Based Development
Describe the common challenges faced by software development teams. Explain the role of version control in mitigating these challenges. Describe the principles of collaboration shared by effective development teams.- Teams without Version Control
- Multiple developers often work together on a piece of Salesforce functionality at the same time in different Sandboxes
- When changes are pushed from dev orgs to the sandbox org, if there is no merge process:
- They can overwrite each other’s changes
- If the changes made directly in the sandbox are overwritten, you can’t go back to recapture them
- Strong developers can put in place processes to prevent these things, but this requires time, energy, and careful planning
- Lack of tools constrain teams operating like this
- Version Control to the Rescue
- Version control exists to solve these problems
- Git is an example of version control
- How Version Control Helps Development in Teams
- Broadly, there are two types of Version Control systems:
- Centralized
- Distributed: give developers flexibility and freedom by providing every collaborator with a copy of the entire repository at any time, including all branches and commits
- Git is a distributed version control system
- Broadly, there are two types of Version Control systems:
- Collaborate to Win
- VCS’s like Git still only address part of the problem
- Breaking down silos and embracing more perspectives and conversations can enable your team to deliver better software
- GitHub is a collaboration platform built on top of Git that aims to accomplish this. It provides:
- Community space where you can share your work
- See your team’s work
- Complete code reviews
- Connect integrations that help you build, test, and deploy your code
- GitHub is home to the largest collection of open source projects in the world
- Being adopted by progressive organizations who recognize the benefits of open, collaborative development
- Being adopted by progressive organizations who recognize the benefits of open, collaborative development
- GitHub is a collaboration platform built on top of Git that aims to accomplish this. It provides:
- Teams that do not use version control can have changes overwritten by other users
- Version control eases the burden of collaboration among team members by providing a way to organize work from many team members
Learn Where GitHub Fits in the Development Lifecycle
List the essential tools in the modern developer’s toolkit. Explain how Git and GitHub work together within the software development lifecycle (SDLC). Describe GitHub’s place in the center of the software development ecosystem.- Differences Between Git and GitHub
- Git and GitHub share a name and a mission, but they are not the same thing
- Git Is a Version Control Application
- Git is the application that keeps track of everything related to the changes on your project over time, including:
- Repositories: collection of source files that compile the project
- Commits: snapshot of the project at a specific point in time
- Branch: series of commits that keep experimental code separate from tested production code. Create branches when working on new features, bugs, or other changes.
- Merge: combined history of two or more branches. Generally, you merge feature branch into the deployed branch.
- Tag: pointer to a specific commit, which provides a persistent reference to an event. Often used with semantic versioning to represent points when the application was released.
- Git is the application that keeps track of everything related to the changes on your project over time, including:
- GitHub Is a Collaboration Platform
- GitHub is a host for Git repositories with collaboration features that let you apply and test code changes
- GitHub serves as a “remote”, in Git terms, giving developers an accessible source of truth for their shared work
- GitHub also has a few key terms:
- Issues: place for general discussion, new features, bugs, etc.
- Pull Request: package of commits you’re requesting to be merged into default branch. Provides a place to discuss the changes you’re proposing and invite other team members to comment. Helps you see results of automated tests and other integrations.
- Provides a highly transparent and contextual environment for developers to do their work
- In short: Git handles version control and GitHub handles collaboration
- The Modern Developer’s Toolkit
- Hundreds of integrators have developed tools to customize and extend GitHub’s functionality to user preferences.
- Includes tools for tasks like: Project management, Continuous integration testing, Deployment, Code review
- GitHub can easily integrate with Salesforce Developer Experience (Salesforce DX)
- Salesforce DX is a set of tools that streamline the development life cycle and shift the source of truth from the org to the VCS
- Developers also generally prefer to work locally in an Integrated Development Environment (IDE)
- Examples: Sublime text, VSCode with Salesforce Extensions
- Continuous Integration (CI) and Continuous Deployment (CD) applications are powerful tools you can add to your workflow:
- These integrations test, build, and deploy your project based on specifications stored in the repository
- Other possible integrations include code quality checking tools, dependency management, and automated security checks
- GitHub’s API and webhooks make it easy for new integrations to be added
- Hundreds of integrators have developed tools to customize and extend GitHub’s functionality to user preferences.
- Customize Workflows to Meet Your Needs
- Perform lightweight project management with GitHub’s built-in projects, or something more fully-featured like ZenHub - options are endless
- Perform lightweight project management with GitHub’s built-in projects, or something more fully-featured like ZenHub - options are endless
- Continuous integration is an essential tool in the modern developer’s toolkit
Discover Collaboration within GitHub
Build organizational structures that facilitate collaboration. List the most commonly visited sections of a GitHub repository. Explain the collaboration features that exist alongside your source code in GitHub.- Tour a GitHub Repository
- Repositories are the most basic element of GitHub
- Best conceptualized as a project folder, but one that includes simple, powerful tools for collaborating
- Contains all the files associated with a project, including documentation, and each file’s revision history
- Repositories are the most basic element of GitHub
- Set Up Your GitHub Organization
- Setting up teams and organizations on GitHub makes collaboration process much easier
- When signing up for GitHub, you automatically get a user account
- User account permissions are pretty simple - you add people as collaborators to specific repositories
- Organization accounts provide more granular control over repository permissions
- Create Teams of people and then give those teams access to specific repositories - teams are a powerful feature
- Permissions can be assigned at the team level or on a user-by-user basis
- Code in a Repository
- Code view is where you find the files in the repository, also called the root of the project
- Shows the default branch, initially called “master,” at first. You can toggle between branches.
- Use Issues for Project Discussions
- Issues are a threaded discussion (like a forum) incorporated right into a GitHub repo
- Use them to track bugs and feature requests and assign them to specific team members
- Simple, lightweight, meant to be used in conjunction with other GitHub features
- Designed to encourage discussion, collaboration, community involvement
- Pull Requests
- Pull Requests are comparisons between two branches, typically between main and another branch used for code in development
- Represents a change to the code
- Can mean adding, modifying, or deleting files made on a branch which the author would like to incorporate in another branch
- Frequently, the work in a pull request starts from an issue
- Pull requests are also a place for an extended conversation about the changes between the branches
- If a bug is accidentally introduced, another developer might catch it and make a comment on it
- Pull requests help you write better software by facilitating code review and showing status of automated tests
- Compares code, provides a platform for conversing about the code, encourages thorough code review, and works with a variety of integrations
- Actions
- GitHub Actions enable you to create custom software development lifecycle workflows directly in the repo
- Write individual tasks, called actions, and combine them to create a custom workflow
- These custom automated processes can build, test, package, release or deploy any code project on GitHub
- Enables you to build robust CI/CD capabilities directly in your repository
- GitHub Actions enable you to create custom software development lifecycle workflows directly in the repo
- Use Projects to Organize Your Work
- Projects bring issues and pull requests together to make tracking and planning larger-scale work more intuitive
- Projects let you visualize work with Kanban style boards, moving task cards, issues, and pull requests along custom columns
- Projects can also be created at the repo or organization level, incorporating issues or pull requests from multiple repos onto a single planning page
- View the files within a GitHub repository from the code tab
- Organization accounts are best suited for large, diverse teams with many projects
Work with the GitHub Workflow
List the steps in the GitHub workflow. Explain the difference between the remote and local working environments. Complete the steps to create a new file and make changes to an existing file.- Overview of the GitHub Workflow
- GitHub Workflow is a lightweight workflow that lets you experiment with ideas without compromising production code. Main steps:
- Create a branch off of main
- Make commits
- Open a pull request
- Collaborate
a. Make more commits
b. Discuss and review code with team - Deploy for final testing
- Merge your branch into the main branch
- The rest of this section delves into these steps
- Creating a branch: key concept within Git, everything lives on a branch. When experimenting with a new feature or fixing an issue, do so by creating a new branch of the project.
- Make commits: commit changes to code files to the feature branch
- Open a Pull Request and collaborate: Open a pull request to start discussing your changes. Best practices is to open a pull request as early as possible, which gives visibility to teammates during the process.
- Merge to main branch: Once the team approves the change, deploy and merge the pull request from the feature branch into the main branch
- GitHub Workflow is a lightweight workflow that lets you experiment with ideas without compromising production code. Main steps:
- Working on GitHub Versus Working Locally
- Its possible to make changes directly on GitHub, but most developers prefer to work on their local machine so they can make changes in their favorite IDE/text editor
- Remote Repository: copy of the repo on GitHub and source of truth which all team members synchronize their changes with
- Local Repositories: git repos stored on a person’s computer. If linked to a remote repo, then full repo is a full copy with everything on the remote repo, with all files, branches, and history.
- Local and remote repos only interact when you run one of four network commands in Git:
git clone
,git fetch
,git pull
, andgit push
- To clone a repo, copy the <CLONE-URL> available when you click the green “Code” button from the “Code” tab, Ex: https://github.com/bitcoin/bitcoin.git
- To retrieve a full copy of the repo from GitHub, use the command
git clone <CLONE-URL>
- Then, navigate into the new directory created by that operation
- Configure Your Local Environment
- Set up a few basic configurations before making changes to the code
- Config command options:
git config --system
: system-wide configurations applicable to all usersgit config --global
: user-level configurations that only apply to your usergit config --local
: repo-level configurations
- Use
git config --list
to see config settings from all three levels - some settings happen automatically - You can’t create commits without a few settings in place:
git config --global user.name "First Last"
git config --global user.email "[email protected]"
- Set up autocrlf as appropriate for your system. This has to do with reconciling differences between how different systems handle line endings and line breaks, which may save some trouble when opening files on different systems:
- Windows:
git config --global core.autocrlf true
- Mac/Linux:
git config --global core.autocrlf input
- Windows:
- Step 1: Create a Branch
- To see a list of local branches, run
git branch
- To create a new branch called myfeaturebranch, run
git branch myfeaturebranch
- “Checkout” to that branch with
git checkout myfeaturebranch
- In git, checkout moves an important “pointer” called HEAD and in this case moves us to a different branch
- To see a list of local branches, run
- Step 2: Make Changes and Commit the Changes to Your Local Repository
- When working locally, Git tracks your history by organizing files and changes in three trees:
- Working: where we add, delete, and make changes to files
- Staging (AKA “index”): a collection of files that represent a discrete unit of work
- History: once we are satisfied with the work we’ve assembled, we take a snapshot of the staging area, called a “commit”
- Here are the relevant commands to making changes to the local repository:
git status
: checks the status of our working tree/staging areagit add README.md
: moves the file from the working tree to the staging areagit commit -m "My first commit"
: takes your first snapshot
- When working locally, Git tracks your history by organizing files and changes in three trees:
- Step 3: Send Changes to the Remote Repository
- Steps above only make changes locally. You need to “push” the changes to see them on the remote.
git push -u origin myfeaturebranch
: creates a remote branch that matches our local one and sets up a tracking relationship between the two branches- After executing this command, you will be asked to enter your GitHub username and password
- This command only needs to be run the first time you push a new branch. From then on, you only need to use
git push
- Step 4: Create a Pull Request
- Steps to open a pull request:
- Go to GitHub on the web
- Click the Pull Request tab
- Click New Pull Request
- In the Base dropdown, choose main
- In the Compare dropdown, choose myfeaturebranch
- Click Create Pull Request, enter a Subject and Comment
- Click Create Pull Request
- Steps to open a pull request:
- Control Code Quality with Code Review
- Pull requests are both a comparison of branches and a way to review code and ensure quality through both human and automated efforts
- Use the Conversation tab to add General Comments on a pull request
- One the Files Changed tab, you can hover over a specific line to see a blue “+” icon, when lets you enter comments on a specific line, called Line Comments
- When making line comments, you can also choose to Start a Review, which lets you group many line comments together with a summary message.
- Once submitted, these can indicate whether it is just a comment, an approval, or a request for changes
- Pull requests can be configured such that they cannot be merged without at least one review
- Highly customizable Automated Tests can be run and reported on right on the pull request, if you’ve integrated CI/CD on a project
- Deploy
- Once the pull request is reviewed and approved, you can deploy your branch and verify the changes in production
- If there are issues, you can roll them back by deploying the existing main back into production
- Merge Your Changes
- When you merge branches, you take the content/history from the feature branch and add it to the content/history of the main branch
- Merging is easy, click Merge pull request, add a merge comment, and then Confirm merge
- Best practice is to establish rules about who should merge a pull request. Some options:
- Person who created the pull request, since they’ll need to resolve issues resulting from the merge
- A single person on the project team, which can ensure consistency or become a bottleneck
- Anyone other than the person who created the pull request, which ensures at least one review has taken place
- When you merge branches, you take the content/history from the feature branch and add it to the content/history of the main branch
- Keeping It All in Sync
- Once a pull request is merged, delete the branch on GitHub
- Merging and deleting on GitHub will not update your local copy. To do this:
git checkout main
, to switch back to your default branchgit pull
, to retrieve all the changes from GitHub- Note
git pull
is a combo command that retrieves the changes from GitHub and updates the branch you’re currently on to include changes from the remote. The commands being combined aregit fetch
andgit merge
- Note
- First step of the GitHub flow is branching
- The command used to synchronize the remote and local working environments is git pull
Work with Teams in GitHub
Translate the GitHub workflow to an effective branching strategy for teams. Resolve merge conflicts on GitHub. Create atomic commits that represent a single unit of work.- Branching Strategies That Work
- Imagine the complexity that results when multiplying all of the branches, commits, and pull requests outlined here, except multiplied by the number of colleagues on your team
- Many teams have done this before, and there are patterns that show success over time
- Generally, branches should be short lived, created to accomplish a specific function, and deleted once merged
- Short lived branches prevent confusion, encourage up-to-date code, and set up developers for iterative improvements to projects
- Long-running branches create problems if not used intentionally
- Examples of intentional usage include a specific development branch if you need multiple levels of deployment-level code
- Challenges with long-running branches commonly come from developers not having the most up-to-date version of each branch
- Questions to consider with your team about branching:
- What branching strategy should we use?
- Which branch is main/deployed code?
- What is the naming convention for our branches?
- How will we use labels and assignees?
- Will we use milestones?
- Will we use Projects?
- Will we have required templates/elements for Issues/pull requests?
- How do we indicate sign-off on pull requests?
- Who merges pull requests?
- Handle Merge Conflicts
- At first may appear intimidating, but resolving them is usually easy
- Resolve the Conflict on the Other Branch
- Steps to resolve:
git checkout new-branch-2
- Checkout to the branch that has a conflictgit pull
- make sure local repo is up to dategit merge origin/main
- notice that you are merging the remote tracking branch and not local copy of maingit status
- after git reports there’s a conflict. Files that have conflicts will be listed underUnmerged Paths
- Open that file in your text editor, check for merge conflict markers: (
<<<<<<<
,=======
,>>>>>>>
) - Both branches' versions of code are present, pick one to keep and delete the other. Deleting the merge conflict markers as well. Save your changes.
- Add and commit the saved changes to resolve the merge conflict:
git add <FILE>
,git commit -m "Commit to resolve merge conflict"
git push
- Push the feature branch to remote
- Steps to resolve:
- Craft Atomic Commits
- Atomic Commits are an important part of creating a readable, informative history of a project
- Version control history lets us look into change history if necessary
- Each commit should be a small, logical unit of change and tell the story of the repo
- The command
git add --patch
(orgit add -p
) lets you add different parts of a file to the staging area, which helps you make comits that are truly logical units of change
- Atomic Commits are an important part of creating a readable, informative history of a project
- Shorter branches are best, but long-lived branches may be appropriate in some cases
- The right amount of change to include in a commit is enough for a small, logical unit of change
Work with Your History in Git
Describe how Git stores data and outline one practical application of this knowledge. View your project history and changes with Git. Use Git commands that let you undo previous changes. Summarize how rebase is related to common merge strategies.- How Git Stores Data
- Commits were previously identified as snapshots of your project
- Each snapshot contains a lot of info - the files compressed in th snapshot are each given a unique SHA-1 hash, called blobs
- In the future, Git will transition from SHA-1 to SHA-256
- Blobs are referenced by a tree, and that tree is referenced by a commit
- As you make changes to files and create new commits, Git identifies the changed files and applies the new SHA-1 hash to the file. Unchanged files retain their existing SHA-1 hash.
- When the hash for a file changes, it references the previous SHA-1 hash as the parent
- View this as the first seven characters of the SHA-1 hash on any commit
- This is similar to how commit history operates - as you create new commits, they reference the previous commit as its parents
- This reference point is very important
- Linear, parent/child relationship creates a consistent history and is what enables Git to merge branches together
- Explore Your History with Git
- It can be helpful to review commit history
- Can review on GitHub.com by selecting commit button from code tab on your project
- Locally, you can use
git log
git log
enables you to display a list of all commits on current branch- By default, shows a lot of info. Modifiers can limit it:
git log -10
only shows the 10 most recent commitsgit log --oneline
shows the first seven characters of the SHA-1 hash and commit messagesgit log --oneline --graph
displays commit history in an ASCII graph showing the different branches in the repository and their commitsgit log --oneline --graph --decorate
displays the same ASCII graph but also includes the branch name(s)
- By default, shows a lot of info. Modifiers can limit it:
- It can be helpful to review commit history
- Compare Versions of Files
- Viewing the differences between your working directory and the staging area helps you
git add
the right files to your commit git diff
helps you review changes between the last commit of your project and various states of the files (ex: working directory or staging area)- Also allows you to compare between any two commits, branches, or tags in the repo. Ex:
git diff 4e3agcb 0cd75d7
- Also allows you to compare between any two commits, branches, or tags in the repo. Ex:
git show <SHA-1>
displays the details of specific commits
- Viewing the differences between your working directory and the staging area helps you
- Undo a Previous Change
- Use commands in this section to fix mistakes, but note some of these commands destructively modify the commit ID
- Undoing Changes
git revert
creates a new commit with changes that are opposite of the commit that is being “undone”- Only use
git revert
if the commit has been pushed to remote - Safe way to undo a specific change, avoiding typical complications that occur when altering commit history of a project
- Amending Commits
git commit --amend
allows you to make modifications to the last commit you made- This alters the commit history of the project, so recommended that you don’t use it if you have already pushed commits to the remote
- Rewind to an Earlier Point in History
- Sometimes you experiment and try new things, but then realize you went down the wrong path and want to go back
git reset
lets you rewind the history of your project, but it alters the commit history- Use
git reset
only when you have not pushed your commits to the remote branch
- Use
- Three types of
git reset
:git reset --soft
takes identified commits and places the changes in the staging area. Helpful if you want to combine a group of commits and combine them into a larger commitgit reset --mixed
is the default mode. It takes all the identified commits and places the changes in the working directory. Helpful if you want to take a group of small commits and combine them to make larger commits, but you can use it to make additional changes to the files and re-create commit historygit reset --hard
takes the identified commits and destroys them permanently- Any uncommitted changes to files that are currently in the working directory or staging area are also deleted.
- This can make you lose work.
- Ex:
git reset --soft HEAD~2
would rewind the branch you are on by two commits (HEAD is a pointer to the tip of your branch)- Changes that had been made in those last two commits would then be reflected in the staging area
- Git Merge Strategies
- Two primary strategies for merging changes to the main branch:
- Recursive Merge: occurs when your feature branch doesn’t have the latest version of code in the branch you’re merging into
- When creating a feature branch, its based off the original branch at its current state. Other collaborators might be merging their changes into the original
- When you create a pull request and merge your changes, a merge commit is created, taking the changes made to your branch and current state of branch you’re merging into and creates a new commit combining those changes.
- Fast-Forward Merge: occurs when there have been no new commits except the ones you’re trying to merge
- Original branch doesn’t have any changes, so the tip is simply fast forwarded to include the changes on your branch
- Git does not create a new merge commit
- Recursive Merge: occurs when your feature branch doesn’t have the latest version of code in the branch you’re merging into
git rebase
command is powerful, and can be used to turn a Recursive Merge into a Fast-Forward merge- Note it rewrites your history, so use it with care
- One of the most popular uses is to create a fast-forward merge when git would have defaulted to a recursive merge
- Remember, recursive merges happen when the branch has new changes since you created your branch - rebase picks up the commit made on your branch and reapplies them after the laast commit on the branch you select
- Allows you to modify the way your commit history looks
- Two primary strategies for merging changes to the main branch:
- References to learn more about Git:
- git revert safely undoes a change at any point in a repo’s history
- rebase enables you to move from a recursive to a fast-forward merge scenario