Message ID | 20200413140918.4778-2-shouryashukla.oo@gmail.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | update gitfaq | expand |
On 2020-04-13 at 14:09:18, Shourya Shukla wrote: > +[[rebasing-and-merging]] > +How do I know when to merge or rebase?:: > + Rebasing and merging two entirely different concepts with different utiilites. > + In Git terms, rebasing means to place changes made in one branch over another branch > + (called base, hence the term, rebase). The commit history of the branch wanting to rebase > + get placed over the branch on the receiving end and it appears as if those changes took > + place in the receiving branch itself. Merging, as the name suggests, merges the latest > + commit of one branch onto the recent branch, making this combination appear as one separate > + commit. > ++ > +Now that we have an idea of the key differences between merging and rebasing, we can look at the > +circumstances when we would want to perform them. Generally, merging is preferred when one desires > +to create a new feature, perform its integration testing with the original codebase, and finally > +integrate it if all tests are passed. One would choose to create a separate branch for this purpose > +and maybe dissolve it when the merge is done. > ++ > +One might want to perform a rebase when they intend to retain the changes made in a separate branch > +into their original branch. In that case, a rebase would place the former changes onto the commit tree > +of the latter. > ++ > +As an additional tip, one can use interactive rebasing, `git rebase -i`, to perform rebasing > +using a text editor GUI (the value of $GIT_EDITOR). Interactive rebase is an excellent utility > +to perform various functions such as editing commit messages, dropping/squashing commits, editing > +commits, etc., all in one package. I like the way you've clearly delineated the two typical use cases. As we know, some people have more other, different workflows, but I think you've given the right amount of detail here. Maybe we should recommend a link to git-rebase(1) to let folks read up on interactive rebase if they're interested in learning more. > +[[files-in-.gitignore-are-tracked]] > +I asked Git to ignore various files, yet they show up as changes in my staging area:: > + One uses '.gitignore' to ignore files from getting tracked in the working tree. This ignores > + the aforementioned files for the whole lifetime of the project unless they area removed from > + the '.gitignore'. Consequently, `git add` does not list these files as 'modified' even if any > + change was made in them and `git status` does not bother to track the changes in these files > + either. > + > + But, '.gitignore' will only ignore the files which were not a part of the repository when they > + were mentioned in the it. Hence, addition of a file to '.gitignore' after it was added to the > + working tree will have no effect and Git will keep tracking them. To amend this mistake, i.e., > + to untrack and completely ignore a tracked file, one has to use `git rm --cached <file>` to > + remove the file from the staging area(i.e. the cache) and not from the repository(presuming > + the file has been added in the 'gitignore'). This will hence make our file behave exactly like > + we described in the paragraph above. I think we want to put a space before these two parentheticals, and I believe it's customary to put a comma after "i.e." or "e.g.". There are some other cases below where I saw these two items as well. > +[[changing-remote-of-the-repository]] > +I want to change the remote of my repository. How do I do that?:: > + A remote is an identifier for a location to which Git pushes your changes as well as fetches > + any new changes(if any). There might be different circumstances in which one might need to change > + the remote: > + > + 1. One might want to update the url of their remote; in that case, the command to use is, > + `git remote set-url <name> <newurl>`. I suspect we may have some users who don't know what name they should use. Should we maybe suggest using "git remote -v" somewhere here to list the remotes and their existing URLs? As an alternative, we could mention that "origin" is the name of the default remote. Also, I think we want to capitalize "URL" when we write it in prose. > + 2. One might want to have two different remotes for fetching and pushing; this generally > + happens in case of triangular workflows. In this case, it is advisable to create a > + separate remote just for fetching/pushing. But, another way can be to change the push > + url using the `--push` option in the `git set-url` command. > + > +[[fetching-and-pulling]] > +How do I know if I want to do a fetch or a pull?:: > + A fetch brings in the latest changes made upstream(i.e. the remote repository we are working on). > + This allows us to inspect the changes made upstream and integrate all those changes(iff we want to) > + or only cherry pick certain changes. Fetching does not have any immediate effects on the local > + repository. Many of us are familiar with "iff", but it is a bit confusing to folks without a mathematical background or people who aren't native English speakers, and so it might be better to avoid it in documentation targeted to newer users. Can we also maybe add a sentence to explain how one accesses the changes? For example, if one has done "git fetch origin", maybe we should say that the branch master on that remote can be viewed with "origin/master". > + A pull is a wrapper for a fetch and merge. This means that doing a `git pull` will not only fetch the > + changes made upstream but integrate them as well with our local repository. The merge may go smoothly > + or have merge conflicts depending on the case. A pull does not allow you to review any changes made > + upstream but rather merge those changes on their own. > ++ > +This is the reason why it is sometimes advised to fetch the changes first and then merge them accordingly > +because not every change might be of utility to the user. > + > +[[checking-out]] > +What is checking out a commit/branch? How do I perform one?:: > + In Git terminology, a 'checkout' serves three purposes, namely: > + > + 1. Go to another commit; I would be "checking out" to that commit and enter a "detached HEAD" > + state, meaning, that the "pointer" called HEAD which tells me where I am right now in my > + working tree is not where it generally should be, i.e., referring to a named branch(say, master). > + Instead the aforementioned pointer is referring to the specified commit. I can now work upon the > + checked out commit and make any changes or just inspect the files at that state. > + > + 2. Go to a different version of a particular file; let's say I want to go to a particular version > + of a file in my working tree. I can again "checkout" to that particular version(i.e., going to a > + particular commit where certain changes were made). This can be done by entering the SHA1 of the > + commit in question. > + > + 3. Go to another branch or create another branch; I would be "checking out" to another tree > + in my local repository. One might expect to enter a detached HEAD here as well but in fact > + does not. This is because HEAD would point to the tip of the checked out branch, something > + which is not a characteristic of a detached HEAD. Let's phrase this so that the common case (that is, checking out a branch) is first (both here and below). That way, the user can say, "Yes, that's exactly what I want to do," and skip the rest. It's good to mention the other parts, but there are some users who are so new that they're not to the point of the other features, and we can help them by letting them skip over the things they don't yet understand. Also, it looks like there may be some trailing whitespace above (which I've trimmed in my message). > ++ > +To checkout to a commit, one can either pass the SHA1 of the commit to be checked out or a reference to it w.r.t. > +the HEAD. To checkout to a particular version of a file, one can use `git checkout <SHA1/reference> <file>`. > +To checkout to an already existing branch, one should use `git checkout <branch-name>`. To simultaneously create > +and checkout to a branch, one can use the `-b` option in the aforementioned command. > +One can observe how versatile the checkout command is, yet due to simplify things even further, two commands were > +introduced in version 2.23 of Git so as to break down the functionalities of `git checkout` and make it learning > +the command easier for a beginner. The commands being `git switch` and `git restore`. Let's prefer spelling out "with regard to" (or "with respect to") for those who aren't native speakers of English. "i.e." and "e.g." are extraordinarily common and are probably understandable, but my experience as a non-native speaker of Spanish and French is that abbreviations are tricky if you're not completely fluent, and "w.r.t." isn't that common in most prose. Maybe we also want to use a term other than "SHA1", such as "object ID" or "hash", seeing as work is ongoing to add a new hash function. > +`git restore` combines the first two features of the checkout as well as functionalities of `git reset` and `git revert` > +at one place so as to improve the functionality of the command. > ++ > +`git switch` perfoms the third functionality of the `git checkout` command, i.e., manipulating branches(creation). I wonder if we should prefer teaching "git switch" and "git restore" over the more complex features of "git checkout", and mention the variants of "git checkout" as a backup for those using older versions of Git. While I don't use them personally, the feedback I've received from others is that they are much easier to use and reason about than git checkout. Overall, let me say that I'm pretty happy with the way this is coming together and I appreciate you coming up with this series. I'm sorry I didn't have more time to look over this earlier before v2.
Shourya Shukla <shouryashukla.oo@gmail.com> writes: > Add more issues and their respective solutions in the 'Common Issues' > section of gitfaq. It probably would have been much easier to discuss if these sections were separate patches. Also, each physical line is way too long to view without line wrapping (even on my wider-than-usual 92 col terminal). Please wrap lines at a more reasonable column, like 65-72. > +[[rebasing-and-merging]] > +How do I know when to merge or rebase?:: > + Rebasing and merging two entirely different concepts with different utiilites. > + In Git terms, rebasing means to place changes made in one branch over another branch > + (called base, hence the term, rebase). The commit history of the branch wanting to rebase > + get placed over the branch on the receiving end and it appears as if those changes took > + place in the receiving branch itself. "the branch wanting to rebase"? Did you mean "the branc being rebased"? Except for that the above looks quite reasonable. > + Merging, as the name suggests, merges the latest > + commit of one branch onto the recent branch, making this combination appear as one separate > + commit. This description is a bit iffy. There is nothing special about "the latest commit" among the commits on the branch being merged---if you had a two-commit side branch and you merged that branch to another branch, the changes made by _both_ commits would appear in the result; I don't find much value in saying "the latest commit of one branch" (besides, merging an early part of a branch alone, while leaving more later parts of the branch still not merged, is a valid thing to do). Merging binds two (or more) lines of histories into one history, reflecting what these branches wanted to do to the files since they forked from their common ancestor and recording the result as one new "merge" commit that is a direct descendant of the tips of these branches. perhaps. [jc: it is impossible to comment on the overlong lines, so I'd remove the '+'(added) sign and reflow the paragraphs] > Now that we have an idea of the key differences between merging > and rebasing, we can look at the circumstances when we would want > to perform them. OK. > Generally, merging is preferred when one desires > to create a new feature, perform its integration testing with the > original codebase, and finally integrate it if all tests are > passed. This is an unsubstantiated claim (opinion) and I do not know if I agree with it. I do not think we want to have such a sentence as if it were our official recommendation in our documentation set---it is OK to write such things on your blog, but not here. > One would choose to create a separate branch for this purpose and > maybe dissolve it when the merge is done. It is unclear what you mean by "dissolve" here. Do you mean "build a new feature on a topic branch, use the branch to polish the feature until it is perfect, and merge it to the trunk, at which point, the topic branch is no longer needed so it can be discarded"? > One might want to perform a rebase when they intend to retain the > changes made in a separate branch into their original branch. This reads as if you are describing: "I want to keep the original, but I want to use the same changes elsewhere" but I do not think it is a good match for "rebase" in the first place. It sounds more like you are talking about cherry-picking. And "merge" is also perfectly fine way to do so, as long as the original development was done based on the right commit. If you originally based your fix on a commit that is too new in the history, even though the problem you wanted to fix appeared much earlier in the history, you obviously cannot fix the problem for an older maintenance track by merging, and at that point, you may either (1) cherry-pick (i.e. duplicate) the fixes to older maintenance track, while keeping the fixes based on a newer codebase; or (2) rebase the fixes, that were originally done on a newer codebase, to the oldest maintenance track that still matters, and then discard the original fixes and instead merge the result of rebasing to the newer codebase. If you can afford to do (2), it is _always_ preferrable to do so, but often you cannot and you end up doing (1). Notice that the preferred workflow has *both* rebasing and merging as crucial elements. It's not like "when to do rebase, and when to merge" as you set out this section to be. It is often more like "you rebase, in preparation to merge". > In that case, a rebase would place the former changes onto the > commit tree of the latter. > As an additional tip, one can use interactive rebasing, `git > rebase -i`, to perform rebasing using a text editor GUI (the value > of $GIT_EDITOR). Interactive rebase is an excellent utility to > perform various functions such as editing commit messages, > dropping/squashing commits, editing commits, etc., all in one > package. I think what the description is lacking *most* is *why* and without that it would not be as useful as it could be to the readers. Why does one want to rebase commits on a branch? When the reader knows the answer to that question clearly, various things "rebase" lets its users do would make sense. In the context of "I now have my first iteration of a topic (be it a feature or a fix)", one would perform rebase because of different reasons (and they are not exclusive): - Your first attempt may have been built on a wrong commit, so you want to restart your topic branch at a different "base". . You may have written a helper function in your code yourself, because you started your topic branch at the latest release tag, but later you may have noticed that the same helper function is already available for your use in the current development version. By restarting your topic branch at a later commit, you do not have to reinvent the helper function yourself, hence you may want to rebase your topic at the tip of the current development version. . You may have developed a fix on top of the latest release tag, but then realized that the bug you fixed was already there in the previous release. You obviously cannot merge your fix directly to the previous release, because doing so would also pull down all the changes in the latest release. By restarting your topic branch with your fix at the previous release point, you can apply the fix (and no other changes that the latest release has) to the earlier codebase. And if your newer codebase is a superset of your older codebase, you can fix the same bug in the newer codebase by simply merging the fix to the newer codebase (and your original topic branch based on the latest release tag is no longer needed, so you can discard it). - Your commits may have unnecessary or wrong code, or log message, or both. They may be in a wrong order. You would rebuild your history, either on the same base or a different one, and tweak each commit as you do so. And "rebase -i" was invented exactly for that purpose. I won't comment on the other sections in this message (I may do so in separate ones). Thanks.
Shourya Shukla <shouryashukla.oo@gmail.com> writes: > +[[files-in-.gitignore-are-tracked]] > +I asked Git to ignore various files, yet they show up as changes in my staging area:: (again, I'll wrap overly long lines, as they were unreviewable otherwise) > + One uses '.gitignore' to ignore files from getting tracked > + in the working tree. This ignores the aforementioned files > + for the whole lifetime of the project unless they area > + removed from the '.gitignore'. At least "they area" -> "they are" is needed, but it is unclear where these two sentences one to go. "to ignore files from getting tracked in the working tree" is why you may want to use the '.gitignore' file. That is OK. But the connection to the next sentence, especially the subject "This ignores", is hard to grok. I am guessing that you want to tell the users something like Paths that match patterns listed in the `.gitignore` are not meant to be tracked. The act of adding a pattern in `.gitignore` that matches a set of paths that are not tracked is a declaration that you do not intend to track these paths and a request by you to Git to help you achieve that goal. but you are trying to state it in a more approachable manner. But I sense that you ended up being unclear. > + Consequently, `git add` does > + not list these files as 'modified' even if any change was > + made in them and `git status` does not bother to track the > + changes in these files either. This part is very much in line with the "you are declaring and requesting". The user does not want to track these paths, and these commands are helping the user to achieve that wish. However, "`git add` does not list ..." is questionable. by definition, Git does not care about contents of any untracked paths, so there is no way for us to say `modified` about them. The primary utility of `git add` is to add a path, which used to be untracked, to the set of the paths that are tracked. So perhaps To help you keep the paths untracked, `git add` does not add the paths that are not tracked and ignored without the `--force` option, and `git status` does not list them as untracked (i.e. possible candidate that you might want to add but forgot). > + But, '.gitignore' will only ignore the files which were not > + a part of the repository when they were mentioned in the > + it. > + Hence, addition of a file to '.gitignore' after it was > + added to the working tree will have no effect and Git will > + keep tracking them. I am not sure wat you mean by the first sentence (even after removing 'the' from "in the it."). It does not matter if you wrote the pattern '*.o' in the .gitignore file one year ago, or 7 seconds ago. As long as hello.o in the working tree is not tracked, it is ignored. Perhaps The `.gitignore` mechanism applies only to the files that are not already tracked. A path that is already tracked will stay to be tracked even if you add a pattern that happens to match it to .gitignore file. > + To amend this mistake, i.e., to untrack > + and completely ignore a tracked file, I'd omit "To amend this mistake, i.e.," from the above, if I were writing this. Also, I see no value in saying "completely" here. It is not like there are ways to half-ignore or fully-ignore ;-). > + one has to use `git rm > + --cached <file>` to remove the file from the staging > + area(i.e. the cache) and not from the repository(presuming > + the file has been added in the 'gitignore'). To untrack a tracked file, without removing it from the working tree, "git rm --cached <file>" can be used. To keep the file ignored after doing so, make sure that `.gitignore` knows that the file is to be ignored (e.g. by adding <file> to `.gitignore`, but you may already have a pattern that match <file> there). Having commented on this section, I am not sure why we need so much description here, instead of clarifying the existing documentation of the mechanism in the Documentation/gitignore.txt file. I think it is better to limit the FAQ list to two kinds of entries: * A topic that spans multiple mechanisms and features that is not easy to explain in a single documentation page may have to be described in place. * Other topics that already have authoritative description with adequate clarity in other pages should just have a summary paragraph that is less than 5 sentences, and a pointer to the authoritative page. The `.gitignore` topic should fall into the latter category. It is a separate issue if Documentation/gitignore.txt has rooms for improvement and if so, I think it is more productive to propose a patch to it there, not adding too much description on the topic here. Thanks.
Shourya Shukla <shouryashukla.oo@gmail.com> writes: > +[[checking-out]] > +What is checking out a commit/branch? How do I perform one?:: > + In Git terminology, a 'checkout' serves three purposes, namely: Well, whoever is asking the question knows what s/he wants to do is to check out a commit/branch and not "grab a version of files from different tree", so this is answering a question that is not asked. Teaching the distinction of two kinds of checkout [*] may be important, but then we should do so by answering a different question ;-) Side note. There are not three but two variants. There is no conceptual difference between checking out a branch and moving to detached HEAD. They are both to prepare extending the history that led to the commit (either the commit that was checked out, or the commit at the tip of the branch that was checked out); what is done to the resulting history is the only difference (if you work on detached HEAD, you can decide which branch to update with after you are finished working, if you stay on a branch, you are committed to update that branch at the time of checking it out). > + 1. Go to another commit; I would be "checking out" > + to that commit and enter a "detached HEAD" state, "Check out" is a direct verb, i.e. "check out the commit", not "check out to the commit". The same thing can be said to other uses in your document about checking out a path out of a tree-ish. > + meaning, that the "pointer" called HEAD which tells > + me where I am right now in my working tree is not > + where it generally should be, i.e., referring to a > + named branch(say, master). Instead the > + aforementioned pointer is referring to the specified > + commit. I can now work upon the checked out commit > + and make any changes or just inspect the files at > + that state. > + > + 2. Go to a different version of a particular file; Who is "going" and where? Isn't it easier to understand if you explained that "checking out a path out of a tree-ish" is to grab a copy of the blob (which is at the path in the tree-ish) and update the working tree with it? "Replace a file in the working tree with the same file in a different commit", perhaps? > + let's say I want to go to a particular version of a "go to" -> "have" would make this understandable, at least to me. > + file in my working tree. I can again "checkout" to > + that particular version(i.e., going to a particular > + commit where certain changes were made). This can be > + done by entering the SHA1 of the commit in question. > + > + 3. Go to another branch or create another branch; I > + would be "checking out" to another tree in my local > + repository. One might expect to enter a detached > + HEAD here as well but in fact does not. It is unclear why one would expect such a behaviour. Is this really a frequently asked question? > + This is > + because HEAD would point to the tip of the checked > + out branch, something which is not a characteristic > + of a detached HEAD. > ++ > +To checkout to a commit, one can either pass the SHA1 of the > +commit to be checked out or a reference to it w.r.t. the HEAD. I do not know what you mean by "or a reference to it w.r.t the HEAD" here.. > +To checkout to a particular version of a file, one can use `git > +checkout <SHA1/reference> <file>`. You are getting confused here. This part belogs to #2 above, i.e. grabbing a path out of a tree-ish as a way to help growing the current line of the history (either branch or the detached HEAD) you are working on. Not an appropriate sentence to have in the section for #3, which is about switching the line of history you are going to grow. > + To checkout to an already > +existing branch, one should use `git checkout <branch-name>`. To > +simultaneously create and checkout to a branch, one can use the > +`-b` option in the aforementioned command. Yes. But drop "to" from "check out to". You "check out a branch", not "check out to a branch". > +One can observe how versatile the checkout command is, yet due to > +simplify things even further, two commands were introduced in > +version 2.23 of Git so as to break down the functionalities of > +`git checkout` and make it learning the command easier for a > +beginner. Drop "even further". A common complaint was that it was too versatile and introducing two separate commands for its two (again, not three) uses was done to make it simpler and easier to learn and use. > +The commands being `git switch` and `git restore`. > ++ > +`git restore` combines the first two features of the checkout as > +well as functionalities of `git reset` and `git revert` at one > +place so as to improve the functionality of the command. Are you sure? I thought you artificially split "switch" into #1 (switch to a detached HEAD) and #3 (switch to a branch) and described "check out paths out of tree-ish to the working tree" as #2, which is what "git restore" is. > +`git switch` perfoms the third functionality of the `git checkout` > +command, i.e., manipulating branches(creation). Ditto. Detach, orphan, creation, and plain branch switching all fall into "switch"'s purview. The distinction to keep in mind is if you are checking out a line of history to work on, or if you are sticking to the current line of history and manipulating working tree files by grabbing contents of paths out of a different tree-ish. Again, I am not sure why we need to have separate description about two primary modes of "git checkout" here, instead of making sure we have serviceable explanation in "git checkout" manual page and point it from here, if "what are two modes of checkout?" is a frequently asked question. For those who started their Git experience with "switch" and "restore" without touching "checkout", the distinction may not even have to be explained. Thanks.
Shourya Shukla <shouryashukla.oo@gmail.com> writes: >+ [[changing-remote-of-the-repository]] >+ I want to change the remote of my repository. How do I do that?:: >+ A remote is an identifier for a location to which Git pushes >+ your changes as well as fetches any new changes(if >+ any). You push changes to a repository. You fetch changes from a repository. Hence, "a location, which you push changes to, as well as fetch new changes from, if any." But a lot more people fetch from repositories than push to repositories, so "a location, which you fetch changes from, as well as push your changes to." may be easier to follow by audiences. In any case there is one crucial and precious thing in what you wrote here. A remote is a name for *A* location, even if you have two URLs (i.e. one used for fetching from, and another used for pushing to). They are to name logically the same place, only the way you reach may be different. For example, you may have an unauthenticated https:// URL for fetching, while the URL you use to the repository may be ssh:// URL. But the important point is that these URLs are about the same repository---if you push over ssh:// URL your changes, you would be able to see the changes over https:// URL that you use for fetching. >+ There might be different circumstances in which one >+ might need to change the remote: Sure. >+ 1. One might want to update the url of their remote; >+ in that case, the command to use is, `git remote >+ set-url <name> <newurl>`. Yes, this truly is "changing" the old one by replacing its old URL with a new URL. >+ 2. One might want to have two different remotes for >+ fetching and pushing; this generally happens in case >+ of triangular workflows. In this case, it is >+ advisable to create a separate remote just for >+ fetching/pushing. Yes, by definition, triangular is about fetching from somebody else and publishing to your own place for others to fetch, so you'd need two remotes, as you are not talking with a single repository. But I find your phrasing quite confusing. "advisable to have two remotes, one for fetching and the other for pushing" would probably be a lot more correct. And I can understand why you did not write so, and instead ended up with your version. In order to reach the goal of having two (one for push and one for fetch), you would "create a separate remote" as you are likely to already have one for one direction (in other words, you didn't want to say "advisable to create two remotes"). You wrote "create a separate remote just for fetching/pushing" and made the direction of the new one vague, because you do not know if that existing one is for fetching or pushing, But I suspect that all of the above would not be as clear to those who need their questions answered as to somebody like me who knows what you want to say already. And you do not want to explain things in a way that only is understood by experts. How about rephrasing the above more like so? 2. One may want to fetch from one repository and push to anther repository---this is often called a "triangular" workflow. As you'd probably have one remote that you use for fetching already created when you cloned the project, you would want to create a separate remote to record the URL you push to. >+ But, another way can be to change >+ the push url using the `--push` option in the `git >+ set-url` command. Do not recommend this when you describe a triangular workflow; it is confusing to readers. Keeping separate fetch and push URLs for a single remote is not triangular. Describe it separately as a different use case, e.g. 3. You may want to push to a repository over a network protocol different from the one you use to fetch from the repository. Perhaps you want unauthenticated https:// URL for fetching from, and use ssh:// URL when you push to, the same remote. In such a case, ... Other than the above nits I picked, overall it is a good idea to raise this question in the FAQ, I would think. Thanks.
On 16/04 12:05, Junio C Hamano wrote: > Shourya Shukla <shouryashukla.oo@gmail.com> writes: > "to ignore files from getting tracked in the working tree" is why > you may want to use the '.gitignore' file. That is OK. But the > connection to the next sentence, especially the subject "This > ignores", is hard to grok. I am guessing that you want to tell the > users something like > > Paths that match patterns listed in the `.gitignore` are > not meant to be tracked. > > The act of adding a pattern in `.gitignore` that matches a > set of paths that are not tracked is a declaration that you > do not intend to track these paths and a request by you to > Git to help you achieve that goal. > > but you are trying to state it in a more approachable manner. But I > sense that you ended up being unclear. I apologise for this. I am understanding the concepts but I fail to put them in words in English. I will try my best to not degrade the quality of important documentation such as this one. > This part is very much in line with the "you are declaring and > requesting". The user does not want to track these paths > Having commented on this section, I am not sure why we need so much > description here, instead of clarifying the existing documentation > of the mechanism in the Documentation/gitignore.txt file. > > I think it is better to limit the FAQ list to two kinds of entries: > > * A topic that spans multiple mechanisms and features that is not > easy to explain in a single documentation page may have to be > described in place. > > * Other topics that already have authoritative description with > adequate clarity in other pages should just have a summary > paragraph that is less than 5 sentences, and a pointer to the > authoritative page. > > The `.gitignore` topic should fall into the latter category. It is > a separate issue if Documentation/gitignore.txt has rooms for > improvement and if so, I think it is more productive to propose a > patch to it there, not adding too much description on the topic > here. I have seen this problem occur a lot so I decided to put it in the FAQ. I will try to shorten it and make it more 'to the point'. Regards, Shourya Shukla
On 20/04 05:57, Junio C Hamano wrote: > Shourya Shukla <shouryashukla.oo@gmail.com> writes: > >+ 2. One might want to have two different remotes for > >+ fetching and pushing; this generally happens in case > >+ of triangular workflows. In this case, it is > >+ advisable to create a separate remote just for > >+ fetching/pushing. > > Yes, by definition, triangular is about fetching from somebody else > and publishing to your own place for others to fetch, so you'd need > two remotes, as you are not talking with a single repository. > > But I find your phrasing quite confusing. I understand. My words turn out to be very ambiguous sometimes. I meant creating a separate remote for fetch and separate one for push. Apologies for the confusion. > "advisable to have two remotes, one for fetching and the other for > pushing" would probably be a lot more correct. > > And I can understand why you did not write so, and instead ended up > with your version. In order to reach the goal of having two (one > for push and one for fetch), you would "create a separate remote" as > you are likely to already have one for one direction (in other > words, you didn't want to say "advisable to create two remotes"). > > You wrote "create a separate remote just for fetching/pushing" and > made the direction of the new one vague, because you do not know if > that existing one is for fetching or pushing, > > But I suspect that all of the above would not be as clear to those > who need their questions answered as to somebody like me who knows > what you want to say already. And you do not want to explain things > in a way that only is understood by experts. How about rephrasing > the above more like so? > > 2. One may want to fetch from one repository and push to > anther repository---this is often called a "triangular" > workflow. As you'd probably have one remote that you use > for fetching already created when you cloned the project, > you would want to create a separate remote to record the URL > you push to. Yep. I will add this. This reads out much better. > >+ But, another way can be to change > >+ the push url using the `--push` option in the `git > >+ set-url` command. > > Do not recommend this when you describe a triangular workflow; it is > confusing to readers. Keeping separate fetch and push URLs for a > single remote is not triangular. I thought it would be OK to describe a maybe *unorthodox* way to do this. I will remove it in the next version. > Describe it separately as a different use case, e.g. > > 3. You may want to push to a repository over a network > protocol different from the one you use to fetch from the > repository. Perhaps you want unauthenticated https:// URL > for fetching from, and use ssh:// URL when you push to, the > same remote. In such a case, ... That sounds quite better. I will incorporate this. Thank you so much for such a detailed review! :) Regards, Shourya Shukla
Shourya Shukla <shouryashukla.oo@gmail.com> writes: > I thought it would be OK to describe a maybe *unorthodox* way to do > this. I will remove it in the next version. The thing is that it is not just unorthodox but it is wrong and broken. Imagine that your 'origin' fetches from upstream that is controlled by me (e.g. at https://github.com/git/git/) and pushes to your publishing repository controled by you. After you fetch from me after my 'master' branch advances, of course, remote/origin/master would be updated in your repository. When you work on your own changes on your 'master' (perhaps you do "pull --rebase origin") and push the result to your publishing repository, which you also call 'origin' because you configured the remotes in your "unorthodox" way, the remote-tracking branch remotes/origin/master would also be updated from your 'master' (i.e. we pretend that we fetched the remote-tracking branches from the same remote immediately after we pushed out). But if you actually fetch from 'origin', I wouldn't have your changes on my 'master' yet, and you won't be seeing your commits in your remotes/origin/master. I.e. the "unorthodox" way breaks your remote-tracking branch, and not recommendable for any usecase. Having said all that, because this is a single-topic FAQ entry that covers only the "remote", we should clarify the existing description in Documentation/git-remote.txt and also possibly config variables the subsystem uses so that anything readers would learn by understanding these three bullet points we just discussed are covered there. And then have a small paragraph that has only the question and "see that section on that manual page" reference, and no duplicated explanation, in the FAQ file.
diff --git a/Documentation/gitfaq.txt b/Documentation/gitfaq.txt index 1cf83df118..fc261cbbf5 100644 --- a/Documentation/gitfaq.txt +++ b/Documentation/gitfaq.txt @@ -223,6 +223,110 @@ a file checked into the repository which is a template or set of defaults which can then be copied alongside and modified as appropriate. This second, modified file is usually ignored to prevent accidentally committing it. +[[rebasing-and-merging]] +How do I know when to merge or rebase?:: + Rebasing and merging two entirely different concepts with different utiilites. + In Git terms, rebasing means to place changes made in one branch over another branch + (called base, hence the term, rebase). The commit history of the branch wanting to rebase + get placed over the branch on the receiving end and it appears as if those changes took + place in the receiving branch itself. Merging, as the name suggests, merges the latest + commit of one branch onto the recent branch, making this combination appear as one separate + commit. ++ +Now that we have an idea of the key differences between merging and rebasing, we can look at the +circumstances when we would want to perform them. Generally, merging is preferred when one desires +to create a new feature, perform its integration testing with the original codebase, and finally +integrate it if all tests are passed. One would choose to create a separate branch for this purpose +and maybe dissolve it when the merge is done. ++ +One might want to perform a rebase when they intend to retain the changes made in a separate branch +into their original branch. In that case, a rebase would place the former changes onto the commit tree +of the latter. ++ +As an additional tip, one can use interactive rebasing, `git rebase -i`, to perform rebasing +using a text editor GUI (the value of $GIT_EDITOR). Interactive rebase is an excellent utility +to perform various functions such as editing commit messages, dropping/squashing commits, editing +commits, etc., all in one package. + +[[files-in-.gitignore-are-tracked]] +I asked Git to ignore various files, yet they show up as changes in my staging area:: + One uses '.gitignore' to ignore files from getting tracked in the working tree. This ignores + the aforementioned files for the whole lifetime of the project unless they area removed from + the '.gitignore'. Consequently, `git add` does not list these files as 'modified' even if any + change was made in them and `git status` does not bother to track the changes in these files + either. + + But, '.gitignore' will only ignore the files which were not a part of the repository when they + were mentioned in the it. Hence, addition of a file to '.gitignore' after it was added to the + working tree will have no effect and Git will keep tracking them. To amend this mistake, i.e., + to untrack and completely ignore a tracked file, one has to use `git rm --cached <file>` to + remove the file from the staging area(i.e. the cache) and not from the repository(presuming + the file has been added in the 'gitignore'). This will hence make our file behave exactly like + we described in the paragraph above. + +[[changing-remote-of-the-repository]] +I want to change the remote of my repository. How do I do that?:: + A remote is an identifier for a location to which Git pushes your changes as well as fetches + any new changes(if any). There might be different circumstances in which one might need to change + the remote: + + 1. One might want to update the url of their remote; in that case, the command to use is, + `git remote set-url <name> <newurl>`. + + 2. One might want to have two different remotes for fetching and pushing; this generally + happens in case of triangular workflows. In this case, it is advisable to create a + separate remote just for fetching/pushing. But, another way can be to change the push + url using the `--push` option in the `git set-url` command. + +[[fetching-and-pulling]] +How do I know if I want to do a fetch or a pull?:: + A fetch brings in the latest changes made upstream(i.e. the remote repository we are working on). + This allows us to inspect the changes made upstream and integrate all those changes(iff we want to) + or only cherry pick certain changes. Fetching does not have any immediate effects on the local + repository. + + A pull is a wrapper for a fetch and merge. This means that doing a `git pull` will not only fetch the + changes made upstream but integrate them as well with our local repository. The merge may go smoothly + or have merge conflicts depending on the case. A pull does not allow you to review any changes made + upstream but rather merge those changes on their own. ++ +This is the reason why it is sometimes advised to fetch the changes first and then merge them accordingly +because not every change might be of utility to the user. + +[[checking-out]] +What is checking out a commit/branch? How do I perform one?:: + In Git terminology, a 'checkout' serves three purposes, namely: + + 1. Go to another commit; I would be "checking out" to that commit and enter a "detached HEAD" + state, meaning, that the "pointer" called HEAD which tells me where I am right now in my + working tree is not where it generally should be, i.e., referring to a named branch(say, master). + Instead the aforementioned pointer is referring to the specified commit. I can now work upon the + checked out commit and make any changes or just inspect the files at that state. + + 2. Go to a different version of a particular file; let's say I want to go to a particular version + of a file in my working tree. I can again "checkout" to that particular version(i.e., going to a + particular commit where certain changes were made). This can be done by entering the SHA1 of the + commit in question. + + 3. Go to another branch or create another branch; I would be "checking out" to another tree + in my local repository. One might expect to enter a detached HEAD here as well but in fact + does not. This is because HEAD would point to the tip of the checked out branch, something + which is not a characteristic of a detached HEAD. ++ +To checkout to a commit, one can either pass the SHA1 of the commit to be checked out or a reference to it w.r.t. +the HEAD. To checkout to a particular version of a file, one can use `git checkout <SHA1/reference> <file>`. +To checkout to an already existing branch, one should use `git checkout <branch-name>`. To simultaneously create +and checkout to a branch, one can use the `-b` option in the aforementioned command. ++ +One can observe how versatile the checkout command is, yet due to simplify things even further, two commands were +introduced in version 2.23 of Git so as to break down the functionalities of `git checkout` and make it learning +the command easier for a beginner. The commands being `git switch` and `git restore`. ++ +`git restore` combines the first two features of the checkout as well as functionalities of `git reset` and `git revert` +at one place so as to improve the functionality of the command. ++ +`git switch` perfoms the third functionality of the `git checkout` command, i.e., manipulating branches(creation). + Hooks -----
Add more issues and their respective solutions in the 'Common Issues' section of gitfaq. Signed-off-by: Shourya Shukla <shouryashukla.oo@gmail.com> --- Documentation/gitfaq.txt | 104 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+)