Category: Developer life

  • Pro Git Chapter 1: Getting Started

    Pro Git Chapter 1: Getting Started

    Getting Started

    This chapter will be about getting started with Git. We will begin at the beginning by explaining some background on version control tools, then move on to how to get Git running on your system and finally how to get it setup to start working with. At the end of this chapter you should understand why Git is around, why you should use it and you should be all setup to do so.

    About Version Control

    What is version control, and why should you care? Version control is a system that records changes to a file or set of files overtime so that you can recall specific versions later. For the examples in this book you will use software source code as the files being version controlled, though in reality you can do this with nearly any type of file on a computer.

    If you are a graphic or web designer and want to keep every version of an image or layout (which you would most certainly want to), a Version Control System (VCS) is a very wise thing to use. It allows you to revert files back to a previous state, revert the entire project back to a previous state, compare changes over time, see who last modified something that might be causing a problem, who introduced an issue and when, and more. Using a VCS also generally means that if you screw things up or lose files, you can easily recover. In addition, you get all this for very little overhead.

    Local Version Control Systems

    Many people’s version-control method of choice is to copy files into another directory (perhaps a time-stamped directory, if they’re clever). This approach is very common because it is so simple, but it is also incredibly error prone. It is easy to forget which directory you’re in and accidentally write to the wrong file or copy over files you don’t mean to.

    To deal with this issue, programmers long ago developed local VCSs that had a simple database that kept all the changes to files under revision control (see Figure 1.1).

    Figure 1.1 Local version control diagram

    One of the more popular VCS tools was a system called rcs, which is still distributed with many computers today. Even the popular Mac OS X operating system includes the rcs command when you install the Developer Tools. This tool basically works by keeping patch sets (that is, the differences between files) from one change to another in a special format on disk; it can then re-create what any file looked like at any point in time by adding up all the patches.

    Centralized Version Control Systems

    The next major issue that people encounter is that they need to collaborate with developers on other systems. To deal with this problem, Centralized Version Control Systems (CVCSs) were developed. These systems, such as CVS, Subversion and Perforce, have a single server that contains all the versioned files, and a number of clients that check out files from that central place. For many years, this has been the standard for version control (see Figure 1.2).

    Figure 1.2 Centralized version control diagram

    This setup offers many advantages, especially over local VCSs. For example, everyone knows to a certain degree what everyone else on the project is doing. Administrators have fine-grained control over who can do what; and it’s far easier to administer a CVCS than it is to deal with local databases on every client.

    However, this setup also has some serious downsides. The most obvious is the single point of failure that the centralized server represents. If that server goes down for an hour, then during that hour nobody can collaborate at all or save versioned changes to anything they’re working on. If the hard disk the central database is on becomes corrupted, and proper backups haven’t been kept, you lose absolutely everything—the entire history of the project except what ever single snapshots people happen to have on their local machines. Local VCS systems suffer from this same problem—whenever you have the entire history of the project in a single place, you risk losing everything.

    Distributed Version Control Systems

    This is where Distributed Version Control Systems (DVCSs) step in. In a DVCS such as Git, Mercurial, Bazaar or Darcs), clients don’t just check out the latest snapshot of the files: they fully mirror the repository. Thus if any server dies, and these systems were collaborating via it, any of the client repositories can be copied back up to the server to restore it. Every checkout is really a full backup of all the data (see Figure 1.3).

    Figure 1.3 Distributed version control diagram

    Furthermore, many of these systems deal pretty well with having several remote repositories they can work with, so you can collaborate with different groups of people in different ways simultaneously with in the same project. This allows you to setup several types of workflows that aren’t possible in centralized systems, such as hierarchical models.

    A Short History of Git

    As with many great things in life, Git began with a bit of creative destruction and fiery controversy. The Linux kernel is an open source software project of fairly large scope. For most of the lifetime of the Linux kernel maintenance (1991-2002), changes to the software were passed around as patches and archived files.

    In 2002, the Linux kernel project began using a proprietary DVCS system called BitKeeper.

    In 2005, the relationship between the community that developed the Linux kernel and the commercial company that developed BitKeeper broke down, and the tool’s free-of-charge status was revoked. This prompted the Linux development community (and in particular Linus Torvalds, the creator of Linux) to develop their own tool based on some of the lessons they learned while using BitKeeper. Some of the goals of the new system were as follows:

    • Speed
    • Simple design
    • Strong support for non-linear development (thousands of parallel branches)
    • Fully distributed
    • Able to handle large projects like the Linux kernel efficiently (speed and data size)

    Since its birth in 2005, Git has evolved and matured to be easy to use and yet retain these initial qualities. It’s incredibly fast, it’s very efficient with large projects, and it has an incredible branching system for non-linear development (See Chapter 3).

    Git Basics

    So, what is Git in a nutshell? This is an important section to absorb, because if you understand what Git is and the fundamentals of how it works, then using Git effectively will probably be much easier for you. As you learn Git, try to clear your mind of the things you may know about other VCSs, such as Subversion and Perforce; doing so will help you avoid subtle confusion when using the tool. Git stores and thinks about information much differently than these other systems, even though the user interface is fairly similar; understanding those differences will help prevent you from becoming confused while using it.

    Snapshots, Not Differences

    The major difference between Git and any other VCS (Subversion and friends included) is the way Git thinks about its data. Conceptually, most other systems store information as a list of file-based changes. These systems (CVS, Subversion, Perforce, Bazaar, and so on) think of the information they keep as a set of files and the changes made to each file over time, as illustrated in Figure 1.4.

    Figure 1.4 Other systems tend to store data as changes to a base version of each file.

    Git doesn’t think of or store its data this way. Instead, Git thinks of its data more like a set of snapshots of a mini filesystem. Every time you commit, or save the state of your project in Git, it basically takes a picture of what all your files look like at that moment and stores a reference to that snapshot. To bee fficient, if files have not changed, Git doesn’t store the file again—just a link to the previous identical file it has already stored. Git thinks about its data more like Figure 1.5.

    Figure 1.5 Git stores data as snapshots of the project over time.

    This is an important distinction between Git and nearly all other VCSs. It makes Git reconsider almost every aspect of version control that most other systems copied from the previous generation. This makes Git more like a mini filesystem with some incredibly powerful tools built on top of it, rather than simply a VCS. We’ll explore some of the benefits you gain by thinking of your data this way when we cover Git branching in Chapter 3.

    Nearly Every Operation Is Local

    Most operations in Git only need local files and resources to operate generally no information is needed from another computer on your network. If you’re used to a CVCS where most operations have that network latency overhead, this aspect of Git will make you think that the gods of speed have blessed Git with unworldly powers. Because you have the entire history of the project right there on your local disk, most operations seem almost instantaneous.

    For example, to browse the history of the project, Git doesn’t need to go out to the server to get the history and display it for you—it simply reads it directly from your local database. This means you see the project history almost instantly. If you want to see the changes introduced between the current version of a file and the file a month ago, Git can look up the file a month ago and do a local difference calculation, instead of having to either ask a remote server to do it or pull an older version of the file from the remote server to do it locally.

    This also means that there is very little you can’t do if you’re offline or off VPN. If you get on an airplane or a train and want to do a little work, you can commit happily until you get to a network connection to upload. If you go home and can’t get your VPN client working properly, you can still work. In many other systems, doing so is either impossible or painful. In Perforce, for example, you can’t do much when you aren’t connected to the server; and in Subversion and CVS, you can edit files, but you can’t commit changes to your database (because your database is offline). This may not seem like a huge deal, but you may be surprised what a big difference it can make.

    Git Has Integrity

    Everything in Git is check-summed before it is stored and is then referred to by that checksum. This means it’s impossible to change the contents of any file or directory without Git knowing about it. This functionality is built into Git at the lowest levels and is integral to its philosophy. You can’t lose information in transit or get file corruption without Git being able to detect it. The mechanism that Git uses for this check summing is called a SHA–1 hash. This is a 40-character string composed of hexadecimal characters (0-9 and a-f) and calculated based on the contents of a file or directory structure in Git. A SHA–1 hash looks something like this:

    24b9da6552252987aa493b52f8696cd6d3b00373
    

    You will see these hash values all over the place in Git because it uses them so much. In fact, Git stores everything not by file name but in the Git database addressable by the hash value of its contents.

    Git Generally Only Adds Data

    When you do actions in Git, nearly all of them only add data to the Git database. It is very difficult to get the system to do anything that is not undoable or to make it erase data in any way. As in any VCS, you can lose or mess up changes you haven’t committed yet; but after you commit a snapshot into Git, it is very difficult to lose, especially if you regularly push your database to another repository.

    This makes using Git a joy because we know we can experiment without the danger of severely screwing things up. For a more in-depth look at how Git stores its data and how you can recover data that seems lost, see "Under the Covers" in Chapter 9.

    The Three States

    Now, pay attention. This is the main thing to remember about Git if you want the rest of your learning process to go smoothly. Git has three main states that your files can reside in: committed, modified, and staged. Committed means that the data is safely stored in your local database. Modified means that you have changed the file but have not committed it to your database yet. Staged means that you have marked a modified file in its current version to go into your next commit snapshot.

    This leads us to the three main sections of a Git project: the Git directory, the working directory, and the staging area.

    Figure 1.6 Working directory, staging area, and git directory

    The Git directory is where Git stores the metadata and object database for your project. This is the most important part of Git, and it is what is copied when you clone a repository from another computer.

    The working directory is a single checkout of one version of the project. These files are pulled out of the compressed database in the Git directory and placed on disk for you to use or modify.

    The staging area is a simple file, generally contained in your Git directory, that stores information about what will go into your next commit. It’s sometimes referred to as the index, but it’s becoming standard to refer to it as the staging area.

    The basic Git workflow goes something like this:

    1. You modify files in your working directory.
    2. You stage the files, adding snapshots of them to your staging area.
    3. You do a commit, which takes the files as they are in the staging area and stores that snapshot permanently to your Git directory.

    If a particular version of a file is in the git directory, it’s considered committed. If it’s modified but has been added to the staging area, it is staged. And if it was changed since it was checked out but has not been staged, it is modified. In Chapter 2, you’ll learn more about these states and how you can either take advantage of them or skip the staged part entirely.

    Installing Git

    Let’s get into using some Git. First things first—you have to install it. You can get it a number of ways; the two major ones are to install it from source or to install an existing package for your platform.

    Installing from Source

    Some people may instead find it useful to install Git from source, because you’ll get the most recent version. The binary installers tend to be a bit behind, though as Git has matured in recent years, this has made less of a difference.

    If you do want to install Git from source, you need to have the following libraries that Git depends on: autotools, curl, zlib, openssl, expat, and libiconv. For example, if you’re on a system that has dnf (such as Fedora) or apt-get (such as a Debian-based system), you can use one of these commands to install the minimal dependencies for compiling and installing the Git binaries:

    $ sudo dnf install dh-autoreconf curl-devel expat-devel gettext-devel
    openssl-devel perl-devel zlib-devel
    
    $ sudo apt-get install dh-autoreconf libcurl4-gnutls-dev libexpat1-dev gettext
    libz-dev libssl-dev
    
    In order to be able to add the documentation in various formats (doc, html,
    info), these additional dependencies are required:
    
    $ sudo dnf install asciidoc xmlto docbook2X
    
    $ sudo apt-get install asciidoc xmlto docbook2x
    
    Note Users of RHEL and RHEL-derivatives like CentOS and Scientific Linux will have to enable the EPEL repository to download the docbook2X package.

    Installing on Linux

    If you want to install Git on Linux via a binary installer, you can generally do so through the basic package-management tool that comes with your distribution. If you’re on Fedora, you can use yum:

    $ yum install git-core 
    

    Or if you’re on a Debian-based distribution like Ubuntu, try apt-get:

    $ apt-get install git-core
    

    Installing on Mac

    There are two easy ways to install Git on a Mac. The easiest is to use the graphical Git installer, which you can download from the SourceForge page: https://sourceforge.net/projects/git-osx-installer/

    The other major way is to install Git via Brew (https://brew.sh/).

    You don’t have to add all the extras, but you’ll probably want to include +svn in case you ever have to use Git with Subversion repositories (see Chapter 8).

    Installing on Windows

    There are also a few ways to install Git on Windows. The most official build is available for download on the Git website. Just go to https://git-scm.com/download/win and the download will start automatically. Note that this is a project called Git for Windows, which is separate from Git itself; for more information on it, go to https://gitforwindows.org.

    To get an automated installation you can use the Git Chocolatey package. Note that the Chocolatey package is community maintained.

    Another easy way to get Git installed is by installing GitHub Desktop. The installer includes a command line version of Git as well as the GUI. It also works well with PowerShell, and sets up solid credential caching and sane CRLF settings. We’ll learn more about those things a little later, but suffice it to say they’re things you want. You can download this from the GitHub Desktop website.

    First-Time Git Setup

    Now that you have Git on your system, you’ll want to do a few things to customize your Git environment. You should have to do these things only once; they’ll stick around between upgrades. You can also change them at any time by running through the commands again.

    Git comes with a tool called git config that lets you get and set configuration variables that control all aspects of how Git looks and operates. These variables can be stored in three different places:

    • /etc/gitconfig file: Contains values for every user on the system and all their repositories. If you pass the option–system to git config, it reads and writes from this file specifically.

    • .gitconfig file: Specific to your user. You can make Git read and write to this file specifically by passing the --global option.

    • config file in the git directory (that is, .git/config) of whatever repository you’re currently using: Specific to that single repository. Each level overrides values in the previous level, so values in .git/config trump those in /etc/gitconfig.

    On Windows systems, Git looks for the .gitconfig file in the $HOME directory (C:\Documents and Settings\$USER for most people). It also still looks for /etc/gitconfig, although it’s relative to the MSys root, which is wherever you decide to install Git on your Windows system when you run the installer.

    Your Identity

    The first thing you should do when you install Git is to set your user name and e-mail address. This is important because every Git commit uses this information, and it’s immutably baked into the commits you pass around:

    $ git config --global user.name "John Doe"
    
    $ git config --global user.email [email protected]
    

    Again, you need to do this only once if you pass the --global option, because then Git will always use that information for anything you do on that system. If you want to override this with a different name or e-mail address for specific projects, you can run the command without the --global option when you’re in that project.

    Your Editor

    Now that your identity is set up, you can configure the default text editor that will be used when Git needs you to type in a message. By default, Git uses your system’s default editor, which is generally Vi or Vim. If you want to use a different text editor, such as Emacs, you can do the following:

    $ git config --global core.editor emacs 
    

    Your Diff Tool

    Another useful option you may want to configure is the default diff tool to use to resolve merge conflicts. Say you want to use vim diff:

    $ git config --global merge.tool vimdiff 
    

    Git accepts kdiff3, tkdiff, meld, xxdiff, emerge, vimdiff, gvimdiff, ecmerge, and opendiff as valid merge tools. You can also set up a custom tool; see Chapter 7 for more information about doing that.

    Checking Your Settings

    If you want to check your settings, you can use the git config --list command to list all the settings Git can find at that point:

    $ git config --list
    
    user.name=Hoang Thanh Son
    
    [email protected]
    
    color.status=auto
    
    color.branch=auto
    
    color.interactive=auto
    
    color.diff=auto ... 
    

    You may see keys more than once, because Git reads the same key from different files (/etc/gitconfig and .gitconfig, for example). In this case, Git uses the last value for each unique key it sees. You can also check what Git thinks a specific key’s value is by typing git config key:

    $ git config user.name Hoang Thanh Son 
    

    Getting Help

    If you ever need help while using Git, there are three ways to get the manual page (manpage) help for any of the Git commands:

    $ git help <verb>
    $ git <verb> --help
    $ man git-<verb> 
    

    For example, you can get the manpage help for the config command by running

    $ git help config 
    

    These commands are nice because you can access them anywhere, even offline. If the man pages and this book aren’t enough and you need in-person help, you can try the #git or #github channel on the Freenode IRC server(irc.freenode.net). These channels are regularly filled with hundreds of people who are all very knowledgeable about Git and are often willing to help.

    Summary

    You should have a basic understanding of what Git is and how it’s different from the CVCS you may have been using. You should also now have a working version of Git on your system that’s set up with your personal identity. It’s now time to learn some Git basics.

    If you can read only one chapter to get going with Git, this is it. This chapter covers every basic command you need to do the vast majority of the things you’ll eventually spend your time doing with Git. By the end of the chapter, you should be able to configure and initialize a repository, begin and stop tracking files, and stage and commit changes. We ‘ll also show you how to setup Git to ignore certain files and file patterns, how to undo mistakes quickly and easily, how to browse the history of your project and view changes between commits, and how to push and pull from remote repositories.

  • Command Tip, Tip and Tips

    Command Tip, Tip and Tips

    Bài này hỗ trợ anh em khá nhiều trong việc sử dụng Command Line trong công việc, tuy nhiên mình sẽ giới hạn ở UNIX-like command thôi, dùng ở Linux, Mac, BSD ý.

    TIP 1: Search History Command

    Trong mấy năm thấy mọi người dùng nút up để mò lại những câu lệnh đã gõ. Ví dụ mình gõ lsof -i :22 và sau đó gõ 5 câu lệnh nữa, vậy là mình sẽ cần ấn nút up 5 lần. Nghe có vẻ mất thời gian và tay to và nhiều câu lệnh quá dài hay khó nhớ.

    Tình cơ thì Linux hay Mac đều lưu trữ lại câu lệnh mà mình đã gõ, có thể tìm thấy ở các file .history hay đơn giản là gõ history

    Mình thêm |tail để lấy ra các lệnh gần nhất thôi

    Vậy là chúng ta có thể history | grep {batkicaigi} để tìm kiếm

    Vậy vẫn hơi lâu, nếu ấn một nút để search thì sao, rất may cái nãy cũng được hỗ trợ luôn Ctrl + R và gõ thôi

    Vấn đề nữa xảy ra, quá ít kết quả được hiển thị, khá là khó chịu. Sau một hồi search thì phát hiện ra có nhiều thứ hỗ trợ mình trong đó có thằng này: peco, một tool filter được viết bằng Go Lang, chúng ta có thể truyền bất kì cái gì vào trong pipe của câu lệnh, từ history, ls, text file hoặc bất kì cái gì.

    Giờ hãy kết hợp history search (Ctrl + R) và peco.

    How to install

    $ brew install peco
    ...
    $ peco --version
    $ peco version v0.5.1
    

    À đấy là MAC còn cái khác thì chịu khó đọc cái này.

    Tiếp theo thì sửa cái .zshrc hoặc .bashrc, tùy xem bạn dùng cái gì, đơn giản là sửa binding key cho phím Ctrl + R thôi.

    # Peco history selection
    function peco-history-selection() {
      local tac
      if which tac > /dev/null; then
        tac="tac"
      else
        tac="tail -r"
      fi
      BUFFER=$(history -1000 | eval $tac | cut -c 8- | peco --query "$LBUFFER")
      CURSOR=$#BUFFER
    }
    zle -N peco-history-selection
    bindkey '^R' peco-history-selection
    

    và reload lại

    $ source .zshrc (or .bash_rc)
    

    Thành quả nè

    Còn mấy cái liên quan đến peco nữa nhưng để dịp sau vậy.

  • Git Command Tips for Pros – Chap 1

    Git Command Tips for Pros – Chap 1

    Hôm nay mình sẽ tiếp tục với Git, bài này thực ra định để trong Series: Git from noob to master, tuy nhiên thì thấy cũng không hay ho lắm, nên quyết định tách riêng.

    Những ai cần đọc bài này

    Thực ra thì ai cũng đọc được, nhưng dùng thì không phải ai cũng cần, ví dụ nếu bạn quen thuộc với git graph (Tool Git GUI nào cũng có) và bạn thực sự hiểu thì cũng không cần lắm, tuy nhiên có một số command vẫn cần thiết, vì Tool không bao giờ toàn năng cả.

    Super Strong git help everyday


    git help everyday
    

    Câu lệnh này thực sự strong,

    Nó sẽ chỉ cho bạn biết các câu lệnh bạn cần dùng với các use-case, role khác nhau, ví dụ: Bạn là thằng dev đơn thuần hay là thằng quản lý repository.

    Git log với các tham số

    Thường thì ae sẽ làm như này

    git log
    

    hay ấn nhiều hơn một chút

    git log --oneline --graph
    

    để có cái sự đẹp đẽ như này

    Về cơ bản đều sử dụng git log, git log hỗ trợ một số tham số dòng lệnh, rất mạnh mẽ, đặc biệt là khi được sử dụng kết hợp để filter, đây là mấy cái khá hay ho

    • –author = "Son Hoang" – Chỉ hiển thị các cam kết được thực hiện bởi một tác giả nào đó, tất nhiên là dùng tên hiển thị
    • –name-only – Chỉ hiển thị tên của các tệp đã thay đổi
    • –oneline – Hiển thị dữ liệu cam kết được nén thành một dòng
    • –graph – Hiển thị cây phụ thuộc cho tất cả các xác nhận
    • –reverse – Hiển thị các cam kết theo thứ tự ngược lại (Cam kết cũ nhất trước)
    • — after – Hiển thị tất cả các cam kết đã xảy ra sau một số ngày nhất định
    • — before – Hiển thị tất cả các cam kết đã xảy ra trước một số dữ liệu nhất định Ví dụ: tôi cần tạo report hàng tuần được gửi mỗi thứ Sáu. Vì vậy, mỗi thứ Sáu, tôi sẽ chạy: git log --author="Alex Kras" --after="1 week ago" --oneline, chỉnh sửa một chút là xong.

    Anw: git log có nhiều param khi sử dụng CLI, nó thực sự mạnh và khá tiện hơn so với các GUI Tool, hãy đọc man git-log, một cái nữa --pretty khá là hay ho :).

    À vẫn có phần 2 nữa nhé

  • Git from noob to master – Chapter 2

    Git from noob to master – Chapter 2

    Trong một vài lần chém gió về Git, thấy mọi người có vẻ chưa chú ý nhiều đến Git và sử dụng nó một cách hiệu quả. Nhân đây xin mạn phép chém gió sơ qua để mọi người hoàn thiện.

    Git command

    Merge và Rebase (cont.)

    Tiếp theo lần trước, mình sẽ bắt đầu với merge

    Tại sao cần "merge"?.

    Đơn giản là vì chúng ta lập trình cùng nhau, nếu bạn quen dùng SVN, sẽ thấy là khi 2 người cùng làm việc (tất nhiên là song song với nhau), sẽ nảy sinh nhu cầu tạo một phiên bản là sự kết hợp giữa 2 phiên bản source code của 2 người

    Để merge được chúng ta cần 2 branch, dưới dây là một ví dụ

    alt text

    Chúng ta có 2 issue 55 và 56 trên hệ thống tracking, một cách nào đó developer có thể giải quyết 2 issues bằng một commit nhưng không phải lúc nào cũng thế và đặc biệt là không phải lúc nào cũng tốt, như là khi 1 trong 2 issues đó chưa được giải quyết triệt để tức là commit đó có vấn đề, rất khó để trace.

    Mọi người nên làm cách clear hơn, 1 hoặc 2 developer sẽ fix nó, ở các nhánh khác nhau.

    git checkout -b issue55
    git checkout -b issue56
    
    # -b for new branch
    

    alt text

    Họ modify source code ở mỗi nhánh và commit

    alt text

    Giờ chúng ta cần đưa phần thay đổi của 2 branch issue55 và issue56 vào master.

    git checkout master # change currrent branch to master
    git merge issue55
    ...
    git merge issue56
    

    alt text

    alt text

    Như vậy mỗi khi merge, chúng ta kết hợp 2 branch (hoặc commit, phần 3 mình sẽ giải thích kỹ hơn tại sao lại là commit) vào một nhánh, hoặc nghĩ đơn giản hơn là đưa những thay đổi ở nhánh này vào nhánh kia bằng một commit mới (chứa toàn bộ thay đổi).

    Ops!!! Git merge conflict

    alt text

    Tại sao conflict, đơn giản thôi, khi ở nhánh bạn merge vào, trong ví dụ issues55 là master bạn cũng có thay đổi. Ở ví dụ này là chúng ta có như sau

    alt text

    Mình có thay đổi ở master và issues1 cùng một dòng, git sẽ không biết chọn sự thay đổi nào. Nhiêu bạn sẽ sợ conflict và không biết làm thế nào và hỏi, câu trả lời là không thế nào cả, người merge sẽ là người quyết định. Có thể là chọn một trong 2, chọn cả 2 hoặc có thể phải làm lại cả đoạn đó.

    alt text

    Nghe nè: đừng bao giờ giải quyết conflict khi bạn không biết người khác vừa thay đổi cái gì, thật đấy.

    Rebase

    Cũng là một cách khác để đưa những thay đổi từ nhánh này sang nhánh khác nhưng khác hơn một chút: Bạn sẽ không tạo thêm commit mới mà đưa toàn bộ commit từ nhánh này sang nhánh kia.

    Quay lại với ví dụ conflict ở bên trên. Khi merge master vào nhánh issues1 chúng ta có

    alt text.

    Rebase thì sao:

    git checkout issues1
    git rebase master
    .... # conflict and resolve
    git add HelloWorldApp.java # add conflict file to tracking again
    git rebase --continue
    

    alt text.

    Như vậy có thể thấy là thay vì tạo commit mới, rebase sẽ đưa toàn bộ commit ở branch issues1 từ lúc branch out đặt lên cuối branch master, như vậy coi như là chúng ta không branch out từ một điểm trong quá khứ mà branch out từ lastest commit của master. À quên, vẫn có conflict và giải quyết nó như bình thường nhé :D.

    Advance Rebase (super strong)

    Thế giờ nếu có một nhánh khác được branch out từ nhánh issues1 mình có rebase lên master được không.

    Câu trả lời là có:

    Giả sử chúng ta có nhánh issues2 được branch out từ masterissues3 được branch out từ issues2.

    alt text.

    git rebase --onto master issues2 issues3
    

    Về cơ bản nó có ý nghĩa như sau:

    Hãy checkout nhánh issues3, và tìm các commit từ commit chung của nhánh issues3issues2, sau đó apply chúng vào nhánh master.

    alt text.

    Chú ý: không được rebase các commit mà bạn đã push lên repository. Nếu không ai cũng ghét và mọi người sẽ sỉ nhục và coi thường.

    Cơ bản là thế này, khi rebase bạn bỏ đi các commit và chuyển chúng sang chỗ khác. Khi bạn sửa các commit bằng rebase, từ một nhánh bạn pull từ repository, và push lên. Mọi người sẽ phải apply lại commit của họ và sẽ xảy ra nhất nhiều conflict khi bạn pull change các commit đó của họ về local.

  • F*** the people, who do not add Newline at End of File

    F*** the people, who do not add Newline at End of File

    Nghe có vẻ cứt bò, tuy nhiên sự thật là việc không add một trong trống ở cuối file thực sự là một tội ác

    No Newline at End of File

    Bạn đã bao giờ nhìn thấy dòng chữ ở git

    alt text

    hay ở vim

    alt text

    Ờ thế tại sao git lại báo thế, nó đến từ một quyết định trong quá khứ của Unix

    Một tệp nguồn không trống sẽ kết thúc bằng một ký tự dòng mới, không được đặt ngay trước ký tự dấu gạch chéo ngược (backslash).

    Vì đây là mệnh đề, nên chúng ta sẽ kiểm tra việc vi phạm quy tắc

    Vì vậy, nó chỉ ra rằng, theo POSIX, mọi tệp văn bản (bao gồm các tệp nguồn Ruby và JavaScript) phải kết thúc bằng một ký tự \n, hoặc mới newline (không phải là một dòng mới). Điều này đóng vai trò là eol, hoặc kết thúc của dòng nhân vật. Nó là một dòng Terminator.

    Bây giờ thì gần như mọi chương trình text editor đều hỗ trợ việc tự động thêm 1 dòng trống vào cuối file, ví dụ:

    • vim: mặc định rồi, nên là cứ để nó mặc định thôi
    • VSCode: dùng setting Files: Insert Final Newline
    • Sublime: dùng setting ensure_newline_at_eof_on_save

    Tóm lại là anh em nên thêm 1 dòng vào cuối file code nếu chưa có thì hãy sửa như sau:

    git ls-files -z | while IFS= read -rd '' f; do tail -c1 < "$f" | read -r _ || echo >> "$f"; done
    

    ref: https://unix.stackexchange.com/questions/31947/how-to-add-a-newline-to-the-end-of-a-file

  • How to recover corrupted GIT repository

    How to recover corrupted GIT repository

    GIT corrupted, really?

    Thực sự vấn đề này mình cũng không sure lắm là do đâu, và cũng không chắc vấn đề này có phải là corrupted hay không nhưng sẽ note lại một chút về case này.

    Nạn nhân

    Ngô Hải Đoàn, 1995, Android Dev. Anh ta đang làm việc trên PC, đột nhiên tòa nhà bị mất điện, khi bật máy lại anh ta phát hiện ra anh ta không thể thực hiện các câu lệnh git trên local-repository của mình nữa và mình là thằng cave được gọi support.

    Phán đoán

    Trước khi vào phần phán đoán thì mình có hỏi về source code đã commit chưa, nếu commit rồi thì khả năng recover được rất cao. Câu hỏi thứ 2, source code đó có quan trọng không, nếu có thể re-work trong dưới 30m thì chắc sẽ không có node này.

    Mình sẽ kết thúc phần phán đoán ở đây vì chả có gì để phán đoán cả

    Kiểm tra một chút.

    Trong khi voọc máy của Đoàn thì mình có cố re-init repository nhưng có vẻ không khả quan, kiểm tra một lúc thì có vẻ như các object và ref của git vẫn còn khá ổn. Bạn có thể tự kiểm tra thư mục .git trong local repository của mình.

    Như vậy, nhìn chung khả năng cao branch/commit quan trọng vẫn ổn.

    Thử recover.

    Mình có sử dụng một số câu lệnh git cơ bản như git log hay git init để thử lấy lại commit-id nhưng không thành công.

    Đến đây nhìn chung bạn không thể làm gì với repo này nữa, nên mình sẽ chuyển toàn bộ object của repo này sang một thư mục khác mà vừa clone về. (copy thư mục object trong .git của thư mục cũ sang chỗ tương ứng của thư mục mới)

    Đến đây bạn có một repository giống với remote (chỗ mà bạn clone về) và cộng thêm các commit mà bạn đã commit hoặc đã pull về từ remote.

    Tại sao lại copy objects

    Nhìn chung nếu bạn đã commit thì không sợ mất content. Bởi khi commit git sẽ sinh ra các file object trong thư mục objects, công với log trong logs và một số ref hay info.

    Object name sẽ dài 40 ký tự (SHA1)

    Thư mục object của bạn sẽ trông như này

    alt text

    Tên thư mục sẽ là 2 ký tự đầu trong 40 ký tự. Trong thư mục sẽ có các file với tên là 38 ký tự còn lại.

    Objects sẽ chứa thông tin về file (changed content) để xem được thì cần dùng câu lệnh git(do git mã hóa nên chỉ git xem đc :D): git cat-file

    alt text

    Đến đấy các bạn sẽ đặt câu hỏi thế git quản lý các file thành commit như thế nào

    Từ các objects thì git sẽ dựng lên tree là các phiên bản của thư mục bao gồm các objects.

    alt text

    alt text

    Cứ thế, bằng cách duyệt tree, ta sẽ có 1 tree hoàn chỉnh gồm content của cả một phiên bản (commit).

    Cuối cùng commit sẽ bao gồm 1 tree

    alt text

    Tóm lại cứ còn objects là bạn còn tất cả, việc còn lại là đi tìm commit-id để recover.

    Tìm commit

    Có một vài chỗ để bạn có thể tìm GIT commit-id, thứ nhất đó là thư mục refs

    Refs

    Refs chỉ đơn giản là references của commit. Refs dùng để bạn nhớ lastest commit bằng cách lưu commit id vào thư mục refs.

    alt text

    Ở đây lastest commit của nhánh master đang là b94514784b0b86e84bdd2d66903de5bf7f9722c2.

    Vậy nhớ được tên nhánh là có thể recover lại được. Lúc này bạn sẽ recover toàn bộ tree của nhánh đó và mặc nhiên các commit base trên commit này sẽ có thể trace được.

    logs

    Một chỗ nữa, toàn năng hơn là logs. Log lưu lại lịch sử của từng nhánh.

    alt text

    Bạn có thể xem mình đã tunglamgi trên từng nhánh.

    Đến đây bạn có commit-id rồi việc còn lại là recover bằng câu lệnh git checkout commit-id

    Btw

    Nhìn chung xử lý mấy việc lặt vặt này khá hay và tạo cho mình nhiều cơ hội xử lý các thủ thuật về git.

    Anw: Dù mất kì chuyện gì xảy ra đừng bao giờ xóa thư mục .git 😀

  • Git from noob to master – Chapter 1

    Git from noob to master – Chapter 1

    Trong một vài lần chém gió về Git, thấy mọi người có vẻ chưa chú ý nhiều đến Git và sử dụng nó một cách hiệu quả. Nhân đây xin mạn phép chém gió sơ qua để mọi người hoàn thiện.

    Git là gì

    Câu hỏi cơ bản và đơn giản nhưng thay vì trích dẫn bất kì định nghĩa nào mình sẽ quay sang từ khóa và hinh ảnh

    • SCM – Source code management
    • Linus Torvarlds (Linux)
    • Thay thế BitKeeper trong dự án Linux Kernel

    Cài đặt

    Git cung cấp bộ cài cho tất cả các OS hệ POSIX: Linux, Windows, macOS trên git-scm.

    Sơ lược lịch sử

    alt text.

    Torvalds thổ lộ rằng: ông chưa bao giờ muốn thực hiện quản lý source code, đó là công việc nhàm chán nhất trong thế giới máy tính (trừ database ra). Torvalds cùng các đồng đội sử dụng rất nhiều SCM khác nhau cho đến khi họ thấy phù hợp với BitKeeper(BK), thậm chí BK là nhân tố quan trong trong việc phát triển nhanh chóng của Linux Kernel. Vấn đề duy nhất của BK là một phần mềm độc quyền, tất nhiên có bản miễn phí với các hạn chế cho các open-source project. Larry McVoy(CEO BitMover công ty phát triển BK) vừa muốn hỗ trợ các dự án phần mềm tự do vừa muốn bảo vệ lợi ích của BK cũng như BitMover tất nhiên chừng nào hội phần mềm tự do chưa đe dọa đến lợi ích.

    Năm 2005, Andrew "Tridge" Tridgell đã dịch ngược BK, gần như ngay lập tức BK bỏ việc hỗ trợ Linux, ngược lại Linus cũng ngừng sử dụng BK để quản lý mã nguồn, tuy nhiên Linus chỉ có 3 tháng để chuyển toàn bộ source code sang công cụ mới khi BK chính thức ngừng hoàn toàn việc hỗ trợ. Điều đó nảy sỉnh việc phát triển Git.

    Quá trình phát triển bắt đầu từ ngày 3 tháng 4 nằm 2005, Torvalds công bố dự án vào ngày 6, Git có thể cài đặt trên PC vào ngày 7 và tính năng merge branch được release vào ngày 18. Đến ngày 16/6 Git thực hiện quản lý việc release Linux Kernel v2.6.12

    Có lẽ việc ôn lại lịch sử sẽ kết thúc ở đây, phần tiếp theo sẽ quay lại thực tế sử dụng Git

    Một số khái niệm trong Git

    Repository

    • Repository là khái niệm cơ bản của Git tương đương với project trong GitLab, Gerrit
    • Git có thể tạo bằng câu lệnh git init, thư mục trở thành local repository trong khi đó các repository online như trên GitLab được gọi là remote repository.
    • Lịch sử làm việc đều được lưu trong thư mục khởi tạo git

    Remote

    • Repository hosted in server. Remote repository chính thường được gọi là Origin
    • Các local clone đều liên kết đến remote.
    • 1 local clone can have 0, 1 or many remote.

    Branch – nhánh

    • Branch cũng là một khái niệm mới trong Git mà cần phải làm quen.
    • Branch là các version song song với nhau của Repo.
    • Người dùng làm việc trên các branch mà không làm ảnh hưởng đến live version.

    Một vài branch đặc biệt

    • master – branch mặc định
    • HEAD – branch hiện tại mà người dùng đang làm việc
    • origin/master, origin/xxx, origin2/xxx là các nhánh ở remote repository

    Checkout

    • Checkout là cách người ta chuyển nhánh đề làm việc
    • Ví dụ: Bạn lấy project trên GitLab về và cần chuyển qua nhánh master 2 để làm việc bạn cần checkout sang nhánh master 2: git checkout master2, hoặc cũng có thể bạn cần tạo ra một nhánh mới hãy thêm flag -b trong câu lệnh: git checkout -b dev_another_function.

    Commit

    • Nếu như Branch là nhánh cây, cành cây thì có thể coi commit chính là các nút (node) hoặc cũng có thể là một điểm nào đó trên nhánh.
    • Người ta lưu lịch sử làm việc trong các commit, nói cách khác nếu bạn commit dữ liệu của bạn không thể mất trừ khi bạn xóa hoàn toàn project git.
    • Cách tạo commit cũng đơn giản: git commit -m "Commit Message" hoặc cũng có thể đơn giản là git commit sau đó làm theo hướng dẫn với giao diện text editor(thường là vi, vim, nano, etc, ..)
    • Mỗi commit đều có message và một ID đặc biệt (SHA –hash), từ đó có thể trace được commit

    Nói đến đây mình đột nhiên nhiên phát hiện ra trình bay theo hướng này sẽ khiến mọi người khó hiểu một chút, vì vậy ngay sau đây mình sẽ trình bày về commit một cách rõ hơn, theo một cách nhin khác

    Git Concept

    alt text

    alt text

    2 hình trên đây đã trình bày cách sử dụng git ở local một cách cơ bản

    Nhìn chung một file sẽ có 4 trạng thái như hình thứ nhất

    • Untracked: Trong working directory nhưng git không quản lý, đó là nhưng file tạo mới, được copy vào hay đơn giản là bạn vừa chạy git rm fileName.
    • Unmodified: Rất dễ hiểu, đó là file git quản lý, git ghi nhận rằng file đó chưa có sự thay đổi so với commit hiện tại (HEAD). Có 2 cách để chuyển file vào trạng thái này đó là thêm các file untracked git add hay git commit tức là lưu sự thay đổi đó lại (file sẽ được ghi nhận là ko thay đổi so với commit mới :D, đôi chút confuse).
    • Modified: Là file từ trạng thái unmodified và đã bị edit, tất nhiên khi Crtl + Z toàn bộ step, file sẽ trở lại unmodified.
    • Staged: là trạng thái chuẩn bị được commit, thông thường người dùng không để ý đến trạng thái này, trạng thái này được trình bày khá rõ ràng ở hình thứ 2. Một trạng thái kiểu như git đã ghi nhận sự thay đổi nhưng chưa tạo commit. Để chuyển sang trạng thái staged sử dụng câu lệnh git stage.

    Một tips nhỏ với stage, khi bạn cần commit lên nhánh A mà lại làm việc trên nhánh B thì bạn có thể stage toàn bộ file cần thay đổi và checkout sang nhánh A và commit. Một cách khác đa số mọi người sẽ áp dụng đó là commit trên nhánh B, cherry-pick(sẽ nói ở dưới đây) commit sang A, ngoài ra cũng có cách chuyên nghiệp hơn đó là tạo pack diff.

    Merge và Rebase

    Từ thực tế làm việc trong nhóm sẽ nảy sinh các trường hợp phải kết hợp code của nhiều developer để tạo nên một bản hoàn chỉnh thay vì tiếp tục phát triển song song mãi điều đó nảy sinh ra 2 khái niệm trong git là merge và rebase.